livepilot 1.10.6 → 1.10.8
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 +168 -0
- package/README.md +12 -10
- package/bin/livepilot.js +168 -30
- package/installer/install.js +117 -11
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/m4l_device/livepilot_bridge.js +215 -3
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/atlas/__init__.py +132 -33
- package/mcp_server/atlas/tools.py +56 -15
- package/mcp_server/composer/layer_planner.py +27 -0
- package/mcp_server/composer/prompt_parser.py +15 -6
- package/mcp_server/connection.py +11 -3
- package/mcp_server/corpus/__init__.py +14 -4
- package/mcp_server/creative_constraints/tools.py +206 -33
- package/mcp_server/experiment/engine.py +7 -9
- package/mcp_server/hook_hunter/analyzer.py +62 -9
- package/mcp_server/hook_hunter/tools.py +60 -9
- package/mcp_server/m4l_bridge.py +68 -12
- package/mcp_server/musical_intelligence/detectors.py +32 -0
- package/mcp_server/performance_engine/tools.py +112 -29
- package/mcp_server/preview_studio/engine.py +89 -8
- package/mcp_server/preview_studio/tools.py +22 -6
- package/mcp_server/project_brain/automation_graph.py +71 -19
- package/mcp_server/project_brain/builder.py +2 -0
- package/mcp_server/project_brain/tools.py +55 -5
- package/mcp_server/reference_engine/profile_builder.py +129 -3
- package/mcp_server/reference_engine/tools.py +47 -6
- package/mcp_server/runtime/execution_router.py +66 -2
- package/mcp_server/runtime/mcp_dispatch.py +75 -3
- package/mcp_server/runtime/remote_commands.py +10 -2
- package/mcp_server/sample_engine/analyzer.py +131 -4
- package/mcp_server/sample_engine/critics.py +29 -8
- package/mcp_server/sample_engine/models.py +42 -4
- package/mcp_server/sample_engine/tools.py +48 -14
- package/mcp_server/semantic_moves/__init__.py +1 -0
- package/mcp_server/semantic_moves/compiler.py +9 -1
- package/mcp_server/semantic_moves/device_creation_compilers.py +47 -0
- package/mcp_server/semantic_moves/mix_compilers.py +170 -0
- package/mcp_server/semantic_moves/mix_moves.py +1 -1
- package/mcp_server/semantic_moves/models.py +5 -0
- package/mcp_server/semantic_moves/sound_design_compilers.py +22 -59
- package/mcp_server/semantic_moves/tools.py +15 -4
- package/mcp_server/semantic_moves/transition_compilers.py +12 -19
- package/mcp_server/server.py +75 -5
- package/mcp_server/services/singletons.py +68 -0
- package/mcp_server/session_continuity/models.py +4 -0
- package/mcp_server/session_continuity/tracker.py +14 -1
- package/mcp_server/song_brain/builder.py +110 -12
- package/mcp_server/song_brain/tools.py +77 -13
- package/mcp_server/sound_design/tools.py +112 -1
- package/mcp_server/splice_client/client.py +29 -8
- package/mcp_server/stuckness_detector/detector.py +90 -0
- package/mcp_server/stuckness_detector/tools.py +41 -0
- package/mcp_server/tools/_agent_os_engine/critics.py +24 -0
- package/mcp_server/tools/_composition_engine/__init__.py +2 -2
- package/mcp_server/tools/_composition_engine/harmony.py +90 -0
- package/mcp_server/tools/_composition_engine/sections.py +47 -4
- package/mcp_server/tools/_harmony_engine.py +52 -8
- package/mcp_server/tools/_research_engine.py +98 -19
- package/mcp_server/tools/_theory_engine.py +138 -9
- package/mcp_server/tools/agent_os.py +20 -3
- package/mcp_server/tools/analyzer.py +105 -6
- package/mcp_server/tools/clips.py +46 -1
- package/mcp_server/tools/composition.py +66 -23
- package/mcp_server/tools/devices.py +22 -1
- package/mcp_server/tools/harmony.py +115 -14
- package/mcp_server/tools/midi_io.py +23 -1
- package/mcp_server/tools/mixing.py +35 -1
- package/mcp_server/tools/motif.py +49 -3
- package/mcp_server/tools/research.py +24 -0
- package/mcp_server/tools/theory.py +108 -16
- package/mcp_server/tools/tracks.py +1 -1
- package/mcp_server/tools/transport.py +1 -1
- package/mcp_server/transition_engine/critics.py +18 -11
- package/mcp_server/translation_engine/tools.py +8 -4
- package/package.json +25 -3
- package/remote_script/LivePilot/__init__.py +77 -2
- package/remote_script/LivePilot/arrangement.py +12 -2
- package/remote_script/LivePilot/browser.py +16 -6
- package/remote_script/LivePilot/clips.py +69 -0
- package/remote_script/LivePilot/devices.py +10 -5
- package/remote_script/LivePilot/mixing.py +117 -0
- package/remote_script/LivePilot/notes.py +13 -2
- package/remote_script/LivePilot/router.py +13 -1
- package/remote_script/LivePilot/server.py +51 -13
- package/remote_script/LivePilot/version_detect.py +7 -4
- package/server.json +20 -0
- package/.claude-plugin/marketplace.json +0 -21
- package/.mcpbignore +0 -57
- package/AGENTS.md +0 -46
- package/CODE_OF_CONDUCT.md +0 -27
- package/CONTRIBUTING.md +0 -131
- package/SECURITY.md +0 -48
- package/livepilot/.Codex-plugin/plugin.json +0 -8
- package/livepilot/.claude-plugin/plugin.json +0 -8
- package/livepilot/agents/livepilot-producer/AGENT.md +0 -313
- package/livepilot/commands/arrange.md +0 -47
- package/livepilot/commands/beat.md +0 -77
- package/livepilot/commands/evaluate.md +0 -49
- package/livepilot/commands/memory.md +0 -22
- package/livepilot/commands/mix.md +0 -44
- package/livepilot/commands/perform.md +0 -42
- package/livepilot/commands/session.md +0 -13
- package/livepilot/commands/sounddesign.md +0 -43
- package/livepilot/skills/livepilot-arrangement/SKILL.md +0 -155
- package/livepilot/skills/livepilot-composition-engine/SKILL.md +0 -107
- package/livepilot/skills/livepilot-composition-engine/references/form-patterns.md +0 -97
- package/livepilot/skills/livepilot-composition-engine/references/transition-archetypes.md +0 -102
- package/livepilot/skills/livepilot-core/SKILL.md +0 -184
- package/livepilot/skills/livepilot-core/references/ableton-workflow-patterns.md +0 -831
- package/livepilot/skills/livepilot-core/references/automation-atlas.md +0 -272
- package/livepilot/skills/livepilot-core/references/device-atlas/00-index.md +0 -110
- package/livepilot/skills/livepilot-core/references/device-atlas/distortion-and-character.md +0 -687
- package/livepilot/skills/livepilot-core/references/device-atlas/drums-and-percussion.md +0 -753
- package/livepilot/skills/livepilot-core/references/device-atlas/dynamics-and-punch.md +0 -525
- package/livepilot/skills/livepilot-core/references/device-atlas/eq-and-filtering.md +0 -402
- package/livepilot/skills/livepilot-core/references/device-atlas/midi-tools.md +0 -963
- package/livepilot/skills/livepilot-core/references/device-atlas/movement-and-modulation.md +0 -874
- package/livepilot/skills/livepilot-core/references/device-atlas/space-and-depth.md +0 -571
- package/livepilot/skills/livepilot-core/references/device-atlas/spectral-and-weird.md +0 -714
- package/livepilot/skills/livepilot-core/references/device-atlas/synths-native.md +0 -953
- package/livepilot/skills/livepilot-core/references/device-knowledge/00-index.md +0 -34
- package/livepilot/skills/livepilot-core/references/device-knowledge/automation-as-music.md +0 -204
- package/livepilot/skills/livepilot-core/references/device-knowledge/chains-genre.md +0 -173
- package/livepilot/skills/livepilot-core/references/device-knowledge/creative-thinking.md +0 -211
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-distortion.md +0 -188
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-space.md +0 -162
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-spectral.md +0 -229
- package/livepilot/skills/livepilot-core/references/device-knowledge/instruments-synths.md +0 -243
- package/livepilot/skills/livepilot-core/references/m4l-devices.md +0 -352
- package/livepilot/skills/livepilot-core/references/memory-guide.md +0 -107
- package/livepilot/skills/livepilot-core/references/midi-recipes.md +0 -402
- package/livepilot/skills/livepilot-core/references/mixing-patterns.md +0 -578
- package/livepilot/skills/livepilot-core/references/overview.md +0 -290
- package/livepilot/skills/livepilot-core/references/sample-manipulation.md +0 -724
- package/livepilot/skills/livepilot-core/references/sound-design-deep.md +0 -140
- package/livepilot/skills/livepilot-core/references/sound-design.md +0 -393
- package/livepilot/skills/livepilot-devices/SKILL.md +0 -169
- package/livepilot/skills/livepilot-evaluation/SKILL.md +0 -156
- package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +0 -118
- package/livepilot/skills/livepilot-evaluation/references/evaluation-contracts.md +0 -121
- package/livepilot/skills/livepilot-evaluation/references/memory-promotion.md +0 -110
- package/livepilot/skills/livepilot-mix-engine/SKILL.md +0 -123
- package/livepilot/skills/livepilot-mix-engine/references/mix-critics.md +0 -143
- package/livepilot/skills/livepilot-mix-engine/references/mix-moves.md +0 -105
- package/livepilot/skills/livepilot-mixing/SKILL.md +0 -157
- package/livepilot/skills/livepilot-notes/SKILL.md +0 -130
- package/livepilot/skills/livepilot-performance-engine/SKILL.md +0 -122
- package/livepilot/skills/livepilot-performance-engine/references/performance-safety.md +0 -98
- package/livepilot/skills/livepilot-release/SKILL.md +0 -130
- package/livepilot/skills/livepilot-sample-engine/SKILL.md +0 -105
- package/livepilot/skills/livepilot-sample-engine/references/sample-critics.md +0 -87
- package/livepilot/skills/livepilot-sample-engine/references/sample-philosophy.md +0 -51
- package/livepilot/skills/livepilot-sample-engine/references/sample-techniques.md +0 -131
- package/livepilot/skills/livepilot-sound-design-engine/SKILL.md +0 -168
- package/livepilot/skills/livepilot-sound-design-engine/references/patch-model.md +0 -119
- package/livepilot/skills/livepilot-sound-design-engine/references/sound-design-critics.md +0 -118
- package/livepilot/skills/livepilot-wonder/SKILL.md +0 -79
- package/m4l_device/LivePilot_Analyzer.maxpat +0 -2705
- package/manifest.json +0 -91
- package/mcp_server/splice_client/protos/app_pb2.pyi +0 -1153
- package/scripts/generate_tool_catalog.py +0 -131
- package/scripts/sync_metadata.py +0 -132
|
@@ -293,3 +293,120 @@ def set_track_routing(song, params):
|
|
|
293
293
|
result["output_routing_channel"] = track.output_routing_channel.display_name
|
|
294
294
|
|
|
295
295
|
return result
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@register("set_compressor_sidechain")
|
|
299
|
+
def set_compressor_sidechain(song, params):
|
|
300
|
+
"""Configure a Compressor's sidechain input routing (BUG-A3).
|
|
301
|
+
|
|
302
|
+
Same LOM pattern as set_track_routing — the sidechain properties
|
|
303
|
+
(available_sidechain_input_routing_types / _channels) are on the
|
|
304
|
+
device object and Python's Remote Script accesses them cleanly.
|
|
305
|
+
This used to be routed through the M4L bridge (v1.10.6) but Max JS
|
|
306
|
+
LiveAPI couldn't read the available_* lists in Live 12.3.6, so it's
|
|
307
|
+
back on the Python side where it belongs.
|
|
308
|
+
|
|
309
|
+
Params:
|
|
310
|
+
track_index: 0+ regular, -1/-2 returns, -1000 master
|
|
311
|
+
device_index: Compressor's position in the chain
|
|
312
|
+
source_type (optional): RoutingType display name
|
|
313
|
+
(e.g. "1-DRUMS", "Ext. In", "No Input")
|
|
314
|
+
source_channel (optional): RoutingChannel display name
|
|
315
|
+
(e.g. "Post FX", "Pre FX", "Post Mixer")
|
|
316
|
+
|
|
317
|
+
Omit a param to leave that property unchanged.
|
|
318
|
+
"""
|
|
319
|
+
track_index = int(params["track_index"])
|
|
320
|
+
device_index = int(params["device_index"])
|
|
321
|
+
source_type = params.get("source_type")
|
|
322
|
+
source_channel = params.get("source_channel")
|
|
323
|
+
|
|
324
|
+
track = get_track(song, track_index)
|
|
325
|
+
devices = list(track.devices)
|
|
326
|
+
if device_index < 0 or device_index >= len(devices):
|
|
327
|
+
raise ValueError(
|
|
328
|
+
"Device index %d out of range (track has %d devices)"
|
|
329
|
+
% (device_index, len(devices))
|
|
330
|
+
)
|
|
331
|
+
device = devices[device_index]
|
|
332
|
+
|
|
333
|
+
class_name = device.class_name
|
|
334
|
+
if class_name not in ("Compressor2", "Compressor"):
|
|
335
|
+
raise ValueError(
|
|
336
|
+
"Not a Compressor device (class is %s)" % class_name
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# Older Compressor builds may not expose `sidechain_enabled` as a
|
|
340
|
+
# property; the automatable "S/C On" parameter is the fallback.
|
|
341
|
+
# Try both paths so the sidechain gets enabled whichever surface is
|
|
342
|
+
# available on this Live version.
|
|
343
|
+
try:
|
|
344
|
+
device.sidechain_enabled = True
|
|
345
|
+
except AttributeError:
|
|
346
|
+
# Fallback: find the "S/C On" parameter and toggle it
|
|
347
|
+
for param in device.parameters:
|
|
348
|
+
if param.name == "S/C On":
|
|
349
|
+
param.value = 1
|
|
350
|
+
break
|
|
351
|
+
|
|
352
|
+
result = {
|
|
353
|
+
"ok": True,
|
|
354
|
+
"track_index": track_index,
|
|
355
|
+
"device_index": device_index,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if source_type is not None and source_type != "":
|
|
359
|
+
if not hasattr(device, "available_sidechain_input_routing_types"):
|
|
360
|
+
raise ValueError(
|
|
361
|
+
"This Live build doesn't expose "
|
|
362
|
+
"device.available_sidechain_input_routing_types"
|
|
363
|
+
)
|
|
364
|
+
available = list(device.available_sidechain_input_routing_types)
|
|
365
|
+
matched = None
|
|
366
|
+
for rt in available:
|
|
367
|
+
if rt.display_name == source_type:
|
|
368
|
+
matched = rt
|
|
369
|
+
break
|
|
370
|
+
if matched is None:
|
|
371
|
+
options = [rt.display_name for rt in available]
|
|
372
|
+
raise ValueError(
|
|
373
|
+
"Sidechain input type '%s' not found. Available: %s"
|
|
374
|
+
% (source_type, ", ".join(options))
|
|
375
|
+
)
|
|
376
|
+
device.sidechain_input_routing_type = matched
|
|
377
|
+
|
|
378
|
+
if source_channel is not None and source_channel != "":
|
|
379
|
+
if not hasattr(device, "available_sidechain_input_routing_channels"):
|
|
380
|
+
raise ValueError(
|
|
381
|
+
"This Live build doesn't expose "
|
|
382
|
+
"device.available_sidechain_input_routing_channels"
|
|
383
|
+
)
|
|
384
|
+
available = list(device.available_sidechain_input_routing_channels)
|
|
385
|
+
matched = None
|
|
386
|
+
for ch in available:
|
|
387
|
+
if ch.display_name == source_channel:
|
|
388
|
+
matched = ch
|
|
389
|
+
break
|
|
390
|
+
if matched is None:
|
|
391
|
+
options = [ch.display_name for ch in available]
|
|
392
|
+
raise ValueError(
|
|
393
|
+
"Sidechain input channel '%s' not found. Available: %s"
|
|
394
|
+
% (source_channel, ", ".join(options))
|
|
395
|
+
)
|
|
396
|
+
device.sidechain_input_routing_channel = matched
|
|
397
|
+
|
|
398
|
+
# Read back canonical display names
|
|
399
|
+
try:
|
|
400
|
+
result["sidechain"] = {
|
|
401
|
+
"type": device.sidechain_input_routing_type.display_name,
|
|
402
|
+
"channel": device.sidechain_input_routing_channel.display_name,
|
|
403
|
+
"enabled": bool(getattr(device, "sidechain_enabled", True)),
|
|
404
|
+
}
|
|
405
|
+
except AttributeError:
|
|
406
|
+
# Very old Compressor — fall back to whatever we set above
|
|
407
|
+
result["sidechain"] = {
|
|
408
|
+
"type": source_type or "",
|
|
409
|
+
"channel": source_channel or "",
|
|
410
|
+
"enabled": True,
|
|
411
|
+
}
|
|
412
|
+
return result
|
|
@@ -155,12 +155,23 @@ def modify_notes(song, params):
|
|
|
155
155
|
for note in all_notes:
|
|
156
156
|
note_map[note.note_id] = note
|
|
157
157
|
|
|
158
|
+
# Two-pass: validate every note_id BEFORE mutating any notes. The previous
|
|
159
|
+
# one-pass version raised ValueError mid-loop after some notes had already
|
|
160
|
+
# been mutated in place on the C++ NoteVector — yielding a half-modified
|
|
161
|
+
# state where the caller saw an error but earlier edits silently stuck
|
|
162
|
+
# (until apply_note_modifications was called, which it never was in the
|
|
163
|
+
# error path). Fail-all or apply-all is the safer contract.
|
|
164
|
+
missing = [int(mod["note_id"]) for mod in modifications
|
|
165
|
+
if int(mod["note_id"]) not in note_map]
|
|
166
|
+
if missing:
|
|
167
|
+
raise ValueError(
|
|
168
|
+
"Note IDs not found in clip: %s. No modifications applied." % missing
|
|
169
|
+
)
|
|
170
|
+
|
|
158
171
|
# Apply modifications in-place on the original NoteVector's objects
|
|
159
172
|
modified_count = 0
|
|
160
173
|
for mod in modifications:
|
|
161
174
|
note_id = int(mod["note_id"])
|
|
162
|
-
if note_id not in note_map:
|
|
163
|
-
raise ValueError("Note ID %d not found in clip" % note_id)
|
|
164
175
|
note = note_map[note_id]
|
|
165
176
|
if "pitch" in mod:
|
|
166
177
|
note.pitch = int(mod["pitch"])
|
|
@@ -62,8 +62,20 @@ def dispatch(song, command):
|
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
# Built-in ping — no handler registration needed.
|
|
65
|
+
# BUG-A1: embed remote_script version + supported command set so the
|
|
66
|
+
# MCP server can detect stale installs. An old Remote Script (pre-12.3
|
|
67
|
+
# handler adds) would return an older version here; the MCP server
|
|
68
|
+
# compares and warns the user to reinstall.
|
|
65
69
|
if cmd_type == "ping":
|
|
66
|
-
|
|
70
|
+
try:
|
|
71
|
+
from . import __version__ as rs_version
|
|
72
|
+
except ImportError:
|
|
73
|
+
rs_version = "unknown"
|
|
74
|
+
return success_response(request_id, {
|
|
75
|
+
"pong": True,
|
|
76
|
+
"remote_script_version": rs_version,
|
|
77
|
+
"commands": sorted(_handlers.keys()),
|
|
78
|
+
})
|
|
67
79
|
|
|
68
80
|
handler = _handlers.get(cmd_type)
|
|
69
81
|
if handler is None:
|
|
@@ -197,21 +197,45 @@ class LivePilotServer(object):
|
|
|
197
197
|
self._log("Client disconnected")
|
|
198
198
|
|
|
199
199
|
def _handle_client(self, client):
|
|
200
|
-
"""Read newline-delimited JSON from a connected client.
|
|
200
|
+
"""Read newline-delimited JSON from a connected client.
|
|
201
|
+
|
|
202
|
+
Accumulate raw bytes and only attempt UTF-8 decode on newline-framed
|
|
203
|
+
lines — the previous implementation decoded each recv chunk eagerly
|
|
204
|
+
with ``errors="replace"``, which silently corrupted JSON when a
|
|
205
|
+
multi-byte UTF-8 sequence (non-ASCII filename or rack name) straddled
|
|
206
|
+
the 4096-byte recv boundary. Trailing bytes of the split codepoint
|
|
207
|
+
were converted to U+FFFD, breaking JSON parsing.
|
|
208
|
+
"""
|
|
201
209
|
client.settimeout(1.0)
|
|
202
|
-
buf =
|
|
210
|
+
buf = bytearray()
|
|
211
|
+
MAX_BUF = 4 * 1024 * 1024 # 4 MB
|
|
203
212
|
while self._running:
|
|
204
213
|
try:
|
|
205
214
|
data = client.recv(4096)
|
|
206
215
|
if not data:
|
|
207
216
|
break
|
|
208
|
-
buf
|
|
209
|
-
if len(buf) >
|
|
217
|
+
buf.extend(data)
|
|
218
|
+
if len(buf) > MAX_BUF:
|
|
210
219
|
self._log("Client buffer overflow — disconnecting")
|
|
211
220
|
break
|
|
212
|
-
while
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
while True:
|
|
222
|
+
nl = buf.find(b"\n")
|
|
223
|
+
if nl < 0:
|
|
224
|
+
break
|
|
225
|
+
raw_line = bytes(buf[:nl])
|
|
226
|
+
del buf[: nl + 1]
|
|
227
|
+
try:
|
|
228
|
+
line = raw_line.decode("utf-8").strip()
|
|
229
|
+
except UnicodeDecodeError as exc:
|
|
230
|
+
self._send(client, {
|
|
231
|
+
"id": "unknown",
|
|
232
|
+
"ok": False,
|
|
233
|
+
"error": {
|
|
234
|
+
"code": "INVALID_PARAM",
|
|
235
|
+
"message": "Invalid UTF-8 in request: %s" % exc,
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
continue
|
|
215
239
|
if line:
|
|
216
240
|
self._process_line(client, line)
|
|
217
241
|
except socket.timeout:
|
|
@@ -253,12 +277,26 @@ class LivePilotServer(object):
|
|
|
253
277
|
try:
|
|
254
278
|
self._cs.schedule_message(0, self._process_next_command)
|
|
255
279
|
except AssertionError:
|
|
256
|
-
# ControlSurface is disconnecting — return error instead of
|
|
257
|
-
# running LOM calls on the TCP thread (which would be unsafe)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
280
|
+
# ControlSurface is disconnecting — return an error instead of
|
|
281
|
+
# running LOM calls on the TCP thread (which would be unsafe).
|
|
282
|
+
#
|
|
283
|
+
# The previous version called get_nowait() unconditionally, which
|
|
284
|
+
# would happily drain a different item if one had been enqueued
|
|
285
|
+
# concurrently (e.g. if _drain_queue had just put another). Under
|
|
286
|
+
# the current single-client model the race is theoretical, but the
|
|
287
|
+
# filtered-rebuild below is correct regardless and defends against
|
|
288
|
+
# any future multi-path enqueue.
|
|
289
|
+
remaining = []
|
|
290
|
+
while True:
|
|
291
|
+
try:
|
|
292
|
+
item = self._command_queue.get_nowait()
|
|
293
|
+
except queue.Empty:
|
|
294
|
+
break
|
|
295
|
+
# Drop only OUR own pending item; preserve anything else
|
|
296
|
+
if item[1] is not response_queue:
|
|
297
|
+
remaining.append(item)
|
|
298
|
+
for item in remaining:
|
|
299
|
+
self._command_queue.put(item)
|
|
262
300
|
self._send(client, {
|
|
263
301
|
"id": request_id,
|
|
264
302
|
"ok": False,
|
|
@@ -33,7 +33,10 @@ def get_live_version():
|
|
|
33
33
|
"""Return (major, minor, patch) of the running Live instance.
|
|
34
34
|
|
|
35
35
|
Uses Live.Application.get_application() to read version info.
|
|
36
|
-
|
|
36
|
+
Returns a conservative (12, 0, 0) fallback on detection failure BUT
|
|
37
|
+
does NOT cache the fallback — earlier versions cached any failure,
|
|
38
|
+
which pinned the whole session to the oldest capability tier even
|
|
39
|
+
after Live finished initializing. Only successful reads are cached.
|
|
37
40
|
"""
|
|
38
41
|
global _cached_version
|
|
39
42
|
if _cached_version is not None:
|
|
@@ -49,10 +52,10 @@ def get_live_version():
|
|
|
49
52
|
except AttributeError:
|
|
50
53
|
patch = 0
|
|
51
54
|
_cached_version = (int(major), int(minor), int(patch))
|
|
55
|
+
return _cached_version
|
|
52
56
|
except Exception:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return _cached_version
|
|
57
|
+
# Don't cache failures — next call may succeed once Live is fully up.
|
|
58
|
+
return (12, 0, 0)
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
def has_feature(feature_name):
|
package/server.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.dreamrec/livepilot",
|
|
4
|
+
"description": "323-tool agentic MCP production system for Ableton Live 12 — device atlas, sample engine, composer",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/dreamrec/LivePilot",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "1.10.8",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"identifier": "livepilot",
|
|
14
|
+
"version": "1.10.8",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
3
|
-
"name": "dreamrec-LivePilot",
|
|
4
|
-
"description": "Agentic MCP production system for Ableton Live 12 — 320 tools, 43 domains",
|
|
5
|
-
"owner": {
|
|
6
|
-
"name": "dreamrec",
|
|
7
|
-
"email": "dreamrec@users.noreply.github.com"
|
|
8
|
-
},
|
|
9
|
-
"plugins": [
|
|
10
|
-
{
|
|
11
|
-
"name": "livepilot",
|
|
12
|
-
"description": "Agentic production system for Ableton Live 12 — 320 tools, 43 domains, device atlas, spectral perception, technique memory, sample intelligence, auto-composition, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
13
|
-
"version": "1.10.6",
|
|
14
|
-
"author": {
|
|
15
|
-
"name": "Pilot Studio"
|
|
16
|
-
},
|
|
17
|
-
"source": "./livepilot",
|
|
18
|
-
"category": "integration"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
package/.mcpbignore
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Development files
|
|
2
|
-
.git
|
|
3
|
-
.git-backup-full
|
|
4
|
-
.github
|
|
5
|
-
.claude
|
|
6
|
-
.playwright-mcp
|
|
7
|
-
.pytest_cache
|
|
8
|
-
.venv
|
|
9
|
-
__pycache__
|
|
10
|
-
|
|
11
|
-
# Test and CI
|
|
12
|
-
tests/
|
|
13
|
-
scripts/
|
|
14
|
-
.github/
|
|
15
|
-
|
|
16
|
-
# Build artifacts
|
|
17
|
-
*.pyc
|
|
18
|
-
.DS_Store
|
|
19
|
-
*.egg-info
|
|
20
|
-
.gitignore
|
|
21
|
-
.mcpbignore
|
|
22
|
-
package-lock.json
|
|
23
|
-
|
|
24
|
-
# Untracked Ableton presets (saved by users into m4l_device/)
|
|
25
|
-
m4l_device/*.adv
|
|
26
|
-
|
|
27
|
-
# Credentials and tokens
|
|
28
|
-
.mcpregistry_*
|
|
29
|
-
.env
|
|
30
|
-
.npmrc
|
|
31
|
-
|
|
32
|
-
# Docs and marketing (not needed at runtime)
|
|
33
|
-
# Ship only docs/manual/, docs/assets/, docs/M4L_BRIDGE.md, docs/TOOL_REFERENCE.md
|
|
34
|
-
docs/specs/
|
|
35
|
-
docs/superpowers/
|
|
36
|
-
docs/plans/
|
|
37
|
-
docs/research/
|
|
38
|
-
docs/v2-master-spec/
|
|
39
|
-
docs/LivePilot-1.7-Perception/
|
|
40
|
-
docs/2026-*
|
|
41
|
-
docs/AGENT_OS_V1.md
|
|
42
|
-
docs/COMPOSITION_ENGINE_V1.md
|
|
43
|
-
docs/ableton-library-map.md
|
|
44
|
-
docs/patreon-content.md
|
|
45
|
-
docs/social-banner.*
|
|
46
|
-
docs/screenshots/
|
|
47
|
-
|
|
48
|
-
# Large binary already in User Library after install
|
|
49
|
-
# m4l_device/LivePilot_Analyzer.amxd
|
|
50
|
-
|
|
51
|
-
# Dev config (root-level only — keep livepilot/.mcp.json which the plugin needs)
|
|
52
|
-
/.mcp.json
|
|
53
|
-
.npmignore
|
|
54
|
-
.editorconfig
|
|
55
|
-
CODE_OF_CONDUCT.md
|
|
56
|
-
CONTRIBUTING.md
|
|
57
|
-
SECURITY.md
|
package/AGENTS.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# LivePilot v1.10.6 — Ableton Live 12
|
|
2
|
-
|
|
3
|
-
## Project
|
|
4
|
-
- **Repo:** This directory (LivePilot)
|
|
5
|
-
- **Type:** Agentic MCP production system for Ableton Live 12
|
|
6
|
-
- **Three layers:** Device Atlas (knowledge) + M4L Analyzer (perception) + Technique Memory (learning)
|
|
7
|
-
- **Sister projects:** TDPilot (TouchDesigner), ComfyPilot (ComfyUI)
|
|
8
|
-
- **Design spec:** `docs/specs/2026-03-17-livepilot-design.md`
|
|
9
|
-
|
|
10
|
-
## Architecture
|
|
11
|
-
- **Remote Script** (`remote_script/LivePilot/`): Runs inside Ableton's Python, ControlSurface base class, TCP socket on port 9878
|
|
12
|
-
- **MCP Server** (`mcp_server/`): Python FastMCP server, validates inputs, sends commands to Remote Script
|
|
13
|
-
- **M4L Bridge** (`m4l_device/`): Max for Live Audio Effect on master track, UDP/OSC bridge for deep LOM access
|
|
14
|
-
- UDP 9880: M4L -> Server (spectral data, responses)
|
|
15
|
-
- OSC 9881: Server -> M4L (commands)
|
|
16
|
-
- `livepilot_bridge.js`: 22 bridge commands for LiveAPI access
|
|
17
|
-
- `SpectralCache`: thread-safe, time-expiring data cache (5s max age)
|
|
18
|
-
- Bridge is optional — all core tools work without it
|
|
19
|
-
- **Plugin** (`livepilot/`): Codex plugin (marketplace-compatible: `.Codex-plugin/plugin.json`)
|
|
20
|
-
- **Installer** (`installer/`): Auto-detects Ableton path, copies Remote Script
|
|
21
|
-
|
|
22
|
-
## Key Rules
|
|
23
|
-
- ALL Live Object Model (LOM) calls must execute on Ableton's main thread via schedule_message queue
|
|
24
|
-
- Live 12 minimum — use modern note API (add_new_notes, get_notes_extended, apply_note_modifications)
|
|
25
|
-
- 320 tools across 43 domains: transport, tracks, clips, notes, devices, scenes, mixing, browser, arrangement, memory, analyzer, automation, theory, generative, harmony, midi_io, perception, agent_os, composition, motif, research, planner, project_brain, runtime, evaluation, mix_engine, sound_design, transition_engine, reference_engine, translation_engine, performance_engine, song_brain, preview_studio, hook_hunter, stuckness_detector, wonder_mode, session_continuity, creative_constraints, device_forge, sample_engine, atlas, composer
|
|
26
|
-
- JSON over TCP, newline-delimited, port 9878
|
|
27
|
-
- Structured errors with codes: INDEX_ERROR, NOT_FOUND, INVALID_PARAM, STATE_ERROR, TIMEOUT, INTERNAL
|
|
28
|
-
|
|
29
|
-
## M4L Bridge Notes
|
|
30
|
-
- OSC addresses must be sent WITHOUT leading `/` — Max `udpreceive` passes `/` as part of messagename
|
|
31
|
-
- `str_for_value` requires `call()` not `get()` (it's a function)
|
|
32
|
-
- `get()` in Max JS LiveAPI always returns arrays
|
|
33
|
-
- `warp_markers` is a dict property returning JSON string — use `JSON.parse()`
|
|
34
|
-
- `SimplerDevice.slices` lives on the `sample` child, not the device
|
|
35
|
-
- `replace_sample` only works on Simplers with existing samples
|
|
36
|
-
- Max freezes JS from search path cache, not source directory — copy to `~/Documents/Max 8/`
|
|
37
|
-
|
|
38
|
-
## Binary Patching Workflow (.amxd)
|
|
39
|
-
When modifying .amxd attributes that Max editor won't persist (e.g., `openinpresentation`):
|
|
40
|
-
1. Find the byte sequence in the .amxd binary
|
|
41
|
-
2. Replace with same-byte-count alternative (file size must not change)
|
|
42
|
-
3. Test by loading in Ableton
|
|
43
|
-
4. Structure: 24-byte `ampf` header + `ptch` chunk + `mx@c` header + JSON patcher + frozen deps
|
|
44
|
-
|
|
45
|
-
## Tool Count
|
|
46
|
-
Currently 320 tools. If adding/removing tools, update: README.md, package.json description, livepilot/.Codex-plugin/plugin.json, livepilot/.claude-plugin/plugin.json, server.json, livepilot/skills/livepilot-core/SKILL.md, livepilot/skills/livepilot-core/references/overview.md, AGENTS.md, CLAUDE.md, CHANGELOG.md, tests/test_tools_contract.py, docs/manual/index.md, docs/manual/tool-reference.md
|
package/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
|
|
5
|
-
We are committed to making participation in this project a welcoming and respectful experience for everyone, regardless of background or experience level.
|
|
6
|
-
|
|
7
|
-
## Our Standards
|
|
8
|
-
|
|
9
|
-
Examples of behavior that contributes to a positive environment:
|
|
10
|
-
|
|
11
|
-
- Using welcoming and inclusive language
|
|
12
|
-
- Being respectful of differing viewpoints and experiences
|
|
13
|
-
- Gracefully accepting constructive criticism
|
|
14
|
-
- Focusing on what is best for the community
|
|
15
|
-
- Showing empathy toward other community members
|
|
16
|
-
|
|
17
|
-
## Enforcement
|
|
18
|
-
|
|
19
|
-
Project maintainers are responsible for clarifying standards of acceptable behavior and will take appropriate and fair corrective action in response to any unacceptable behavior.
|
|
20
|
-
|
|
21
|
-
Instances of unacceptable behavior may be reported by opening an issue or contacting the maintainers directly.
|
|
22
|
-
|
|
23
|
-
## Attribution
|
|
24
|
-
|
|
25
|
-
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
26
|
-
|
|
27
|
-
For the full text, see <https://www.contributor-covenant.org/version/2/1/code_of_conduct/>.
|
package/CONTRIBUTING.md
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# Contributing to LivePilot
|
|
2
|
-
|
|
3
|
-
Thank you for your interest in contributing to LivePilot. This guide will help you get started.
|
|
4
|
-
|
|
5
|
-
## Quick Links
|
|
6
|
-
|
|
7
|
-
- [Bug reports](https://github.com/dreamrec/LivePilot/issues/new?template=bug_report.yml)
|
|
8
|
-
- [Feature requests](https://github.com/dreamrec/LivePilot/issues/new?template=feature_request.yml)
|
|
9
|
-
- [Questions & help](https://github.com/dreamrec/LivePilot/discussions)
|
|
10
|
-
|
|
11
|
-
## Development Setup
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
git clone https://github.com/dreamrec/LivePilot.git
|
|
15
|
-
cd LivePilot
|
|
16
|
-
python3 -m venv .venv
|
|
17
|
-
source .venv/bin/activate # macOS/Linux
|
|
18
|
-
.venv/bin/pip install -r requirements.txt
|
|
19
|
-
.venv/bin/pip install pytest pytest-asyncio
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Install the Remote Script
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npx livepilot --install
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Restart Ableton → Preferences → Link, Tempo & MIDI → Control Surface → **LivePilot**
|
|
29
|
-
|
|
30
|
-
### Run Tests
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
pytest tests/ -v
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Tests run without Ableton — they validate tool contracts, schema, and pure Python logic.
|
|
37
|
-
Integration testing with a live session is done manually.
|
|
38
|
-
|
|
39
|
-
## Architecture Overview
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
remote_script/LivePilot/ Python ControlSurface inside Ableton (main thread)
|
|
43
|
-
mcp_server/ FastMCP server — validates inputs, sends TCP to Ableton
|
|
44
|
-
m4l_device/ Max for Live analyzer — UDP/OSC bridge for deep LOM access
|
|
45
|
-
livepilot/ Plugin — skills, slash commands, producer agent
|
|
46
|
-
installer/ Auto-detects Ableton path, copies Remote Script
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
All Live Object Model (LOM) calls execute on Ableton's main thread via `schedule_message`.
|
|
50
|
-
Communication is JSON over TCP, newline-delimited, port 9878.
|
|
51
|
-
|
|
52
|
-
## How to Contribute
|
|
53
|
-
|
|
54
|
-
### Reporting Bugs
|
|
55
|
-
|
|
56
|
-
Use the [bug report template](https://github.com/dreamrec/LivePilot/issues/new?template=bug_report.yml).
|
|
57
|
-
Include:
|
|
58
|
-
|
|
59
|
-
- LivePilot version (`npx livepilot --version`)
|
|
60
|
-
- Ableton Live version
|
|
61
|
-
- Diagnostics output (`npx livepilot --doctor`)
|
|
62
|
-
- Steps to reproduce
|
|
63
|
-
|
|
64
|
-
### Suggesting Features
|
|
65
|
-
|
|
66
|
-
Use the [feature request template](https://github.com/dreamrec/LivePilot/issues/new?template=feature_request.yml).
|
|
67
|
-
Explain the workflow problem before describing the solution.
|
|
68
|
-
|
|
69
|
-
### Submitting Code
|
|
70
|
-
|
|
71
|
-
1. **Fork** the repository
|
|
72
|
-
2. **Create a branch** from `main` (`git checkout -b feat/your-feature`)
|
|
73
|
-
3. **Make your changes** — keep commits focused and atomic
|
|
74
|
-
4. **Run tests** — `pytest tests/ -v` must pass
|
|
75
|
-
5. **Update documentation** if you add or remove tools:
|
|
76
|
-
- Update tool count in `README.md`, `CLAUDE.md`, `package.json`
|
|
77
|
-
- Add an entry to `CHANGELOG.md`
|
|
78
|
-
6. **Open a PR** against `main`
|
|
79
|
-
|
|
80
|
-
### Code Style
|
|
81
|
-
|
|
82
|
-
- **Python:** Follow existing conventions in `mcp_server/`. No linter is enforced yet, but keep it clean.
|
|
83
|
-
- **Remote Script:** All LOM calls must use `schedule_message` — never call the LOM directly from a non-main thread.
|
|
84
|
-
- **M4L Bridge (JS):** Changes to `livepilot_bridge.js` must be tested with the analyzer loaded on the master track in a live Ableton session.
|
|
85
|
-
- **Error codes:** Use structured errors: `INDEX_ERROR`, `NOT_FOUND`, `INVALID_PARAM`, `STATE_ERROR`, `TIMEOUT`, `INTERNAL`.
|
|
86
|
-
|
|
87
|
-
### Commit Messages
|
|
88
|
-
|
|
89
|
-
Use concise, descriptive messages:
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
fix: bridge UTF-8 OSC args, KeyError→INVALID_PARAM
|
|
93
|
-
feat: add per-track loudness analysis
|
|
94
|
-
docs: update tool reference for v1.9.11
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Prefix with `fix:`, `feat:`, `docs:`, `refactor:`, `test:`, or `chore:`.
|
|
98
|
-
|
|
99
|
-
## Tool Count Discipline
|
|
100
|
-
|
|
101
|
-
Currently **320 tools**. If you add or remove a `@mcp.tool()` decorator, update all of these files:
|
|
102
|
-
|
|
103
|
-
- `README.md`
|
|
104
|
-
- `CLAUDE.md`
|
|
105
|
-
- `package.json` description
|
|
106
|
-
- `livepilot/.Codex-plugin/plugin.json`
|
|
107
|
-
- `livepilot/.claude-plugin/plugin.json`
|
|
108
|
-
- `server.json`
|
|
109
|
-
- `livepilot/skills/livepilot-core/SKILL.md`
|
|
110
|
-
- `livepilot/skills/livepilot-core/references/overview.md`
|
|
111
|
-
- `CHANGELOG.md`
|
|
112
|
-
- `tests/test_tools_contract.py`
|
|
113
|
-
- `docs/manual/index.md`
|
|
114
|
-
- `docs/manual/tool-reference.md`
|
|
115
|
-
|
|
116
|
-
## Areas Where Help Is Welcome
|
|
117
|
-
|
|
118
|
-
- **Windows testing** — The installer and Remote Script are tested primarily on macOS
|
|
119
|
-
- **Documentation** — Guides, tutorials, workflow examples
|
|
120
|
-
- **New automation recipes** — Add to the 15 built-in recipes
|
|
121
|
-
- **Theory tools** — Additional modes, non-Western scales, extended harmony
|
|
122
|
-
- **Test coverage** — More contract tests, edge cases
|
|
123
|
-
|
|
124
|
-
## Code of Conduct
|
|
125
|
-
|
|
126
|
-
This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
|
|
127
|
-
By participating, you agree to uphold this code.
|
|
128
|
-
|
|
129
|
-
## License
|
|
130
|
-
|
|
131
|
-
By contributing, you agree that your contributions will be licensed under the [Business Source License 1.1](LICENSE).
|
package/SECURITY.md
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Supported Versions
|
|
4
|
-
|
|
5
|
-
| Version | Supported |
|
|
6
|
-
|---------|-----------|
|
|
7
|
-
| 1.9.x | Yes |
|
|
8
|
-
| < 1.9 | No |
|
|
9
|
-
|
|
10
|
-
## Architecture Security Notes
|
|
11
|
-
|
|
12
|
-
LivePilot operates through three local interfaces:
|
|
13
|
-
|
|
14
|
-
- **TCP 9878** — MCP server ↔ Ableton Remote Script (localhost only)
|
|
15
|
-
- **UDP 9880** — M4L Analyzer → MCP server (localhost only)
|
|
16
|
-
- **OSC 9881** — MCP server → M4L Analyzer (localhost only)
|
|
17
|
-
|
|
18
|
-
All communication is **local only** — no ports are exposed to the network.
|
|
19
|
-
The MCP server runs via stdio transport (stdin/stdout) and does not open HTTP endpoints.
|
|
20
|
-
|
|
21
|
-
## Reporting a Vulnerability
|
|
22
|
-
|
|
23
|
-
If you discover a security vulnerability, please report it responsibly:
|
|
24
|
-
|
|
25
|
-
1. **Do not** open a public issue
|
|
26
|
-
2. Email **security@pilotstudio.dev** with:
|
|
27
|
-
- A description of the vulnerability
|
|
28
|
-
- Steps to reproduce
|
|
29
|
-
- Potential impact
|
|
30
|
-
3. You will receive an acknowledgment within 48 hours
|
|
31
|
-
4. We will work with you to understand and address the issue before any public disclosure
|
|
32
|
-
|
|
33
|
-
If you don't have access to the email, you can use [GitHub's private vulnerability reporting](https://github.com/dreamrec/LivePilot/security/advisories/new).
|
|
34
|
-
|
|
35
|
-
## Scope
|
|
36
|
-
|
|
37
|
-
The following are in scope:
|
|
38
|
-
|
|
39
|
-
- Remote code execution through MCP tool inputs
|
|
40
|
-
- Path traversal in file-handling tools (MIDI I/O, sample loading)
|
|
41
|
-
- Unauthorized access to Ableton session data
|
|
42
|
-
- Denial of service against the MCP server or Remote Script
|
|
43
|
-
|
|
44
|
-
The following are out of scope:
|
|
45
|
-
|
|
46
|
-
- Issues requiring physical access to the machine
|
|
47
|
-
- Issues in Ableton Live itself (report to Ableton)
|
|
48
|
-
- Issues in MCP clients (report to the client maintainer)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "livepilot",
|
|
3
|
-
"version": "1.10.6",
|
|
4
|
-
"description": "Agentic production system for Ableton Live 12 — 320 tools, 43 domains, device atlas, sample intelligence, auto-composition, spectral perception, technique memory, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Pilot Studio"
|
|
7
|
-
}
|
|
8
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "livepilot",
|
|
3
|
-
"version": "1.10.6",
|
|
4
|
-
"description": "Agentic production system for Ableton Live 12 — 320 tools, 43 domains, device atlas, sample intelligence, auto-composition, spectral perception, technique memory, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Pilot Studio"
|
|
7
|
-
}
|
|
8
|
-
}
|