livepilot 1.10.7 → 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.
Files changed (122) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +11 -9
  3. package/bin/livepilot.js +146 -28
  4. package/installer/install.js +117 -11
  5. package/m4l_device/LivePilot_Analyzer.amxd +0 -0
  6. package/m4l_device/livepilot_bridge.js +1 -1
  7. package/mcp_server/__init__.py +1 -1
  8. package/mcp_server/atlas/__init__.py +39 -7
  9. package/mcp_server/atlas/tools.py +56 -15
  10. package/mcp_server/composer/layer_planner.py +27 -0
  11. package/mcp_server/composer/prompt_parser.py +15 -6
  12. package/mcp_server/connection.py +11 -3
  13. package/mcp_server/corpus/__init__.py +14 -4
  14. package/mcp_server/m4l_bridge.py +48 -7
  15. package/mcp_server/runtime/execution_router.py +16 -2
  16. package/mcp_server/runtime/remote_commands.py +6 -0
  17. package/mcp_server/sample_engine/models.py +22 -3
  18. package/mcp_server/semantic_moves/__init__.py +1 -0
  19. package/mcp_server/semantic_moves/compiler.py +9 -1
  20. package/mcp_server/semantic_moves/device_creation_compilers.py +47 -0
  21. package/mcp_server/semantic_moves/mix_compilers.py +170 -0
  22. package/mcp_server/semantic_moves/mix_moves.py +1 -1
  23. package/mcp_server/semantic_moves/models.py +5 -0
  24. package/mcp_server/semantic_moves/tools.py +15 -4
  25. package/mcp_server/server.py +7 -3
  26. package/mcp_server/services/singletons.py +68 -0
  27. package/mcp_server/splice_client/client.py +29 -8
  28. package/mcp_server/tools/analyzer.py +7 -6
  29. package/mcp_server/tools/clips.py +1 -1
  30. package/mcp_server/tools/midi_io.py +10 -0
  31. package/mcp_server/tools/tracks.py +1 -1
  32. package/mcp_server/tools/transport.py +1 -1
  33. package/mcp_server/translation_engine/tools.py +8 -4
  34. package/package.json +25 -3
  35. package/remote_script/LivePilot/__init__.py +29 -9
  36. package/remote_script/LivePilot/arrangement.py +12 -2
  37. package/remote_script/LivePilot/browser.py +16 -6
  38. package/remote_script/LivePilot/devices.py +10 -5
  39. package/remote_script/LivePilot/notes.py +13 -2
  40. package/remote_script/LivePilot/server.py +51 -13
  41. package/remote_script/LivePilot/version_detect.py +7 -4
  42. package/server.json +20 -0
  43. package/.claude-plugin/marketplace.json +0 -21
  44. package/.mcp.json.disabled +0 -9
  45. package/.mcpbignore +0 -60
  46. package/AGENTS.md +0 -46
  47. package/BUGS.md +0 -1570
  48. package/CODE_OF_CONDUCT.md +0 -27
  49. package/CONTRIBUTING.md +0 -131
  50. package/SECURITY.md +0 -48
  51. package/livepilot/.Codex-plugin/plugin.json +0 -8
  52. package/livepilot/.claude-plugin/plugin.json +0 -8
  53. package/livepilot/agents/livepilot-producer/AGENT.md +0 -313
  54. package/livepilot/commands/arrange.md +0 -47
  55. package/livepilot/commands/beat.md +0 -77
  56. package/livepilot/commands/evaluate.md +0 -49
  57. package/livepilot/commands/memory.md +0 -22
  58. package/livepilot/commands/mix.md +0 -44
  59. package/livepilot/commands/perform.md +0 -42
  60. package/livepilot/commands/session.md +0 -13
  61. package/livepilot/commands/sounddesign.md +0 -43
  62. package/livepilot/skills/livepilot-arrangement/SKILL.md +0 -155
  63. package/livepilot/skills/livepilot-composition-engine/SKILL.md +0 -107
  64. package/livepilot/skills/livepilot-composition-engine/references/form-patterns.md +0 -97
  65. package/livepilot/skills/livepilot-composition-engine/references/transition-archetypes.md +0 -102
  66. package/livepilot/skills/livepilot-core/SKILL.md +0 -184
  67. package/livepilot/skills/livepilot-core/references/ableton-workflow-patterns.md +0 -831
  68. package/livepilot/skills/livepilot-core/references/automation-atlas.md +0 -272
  69. package/livepilot/skills/livepilot-core/references/device-atlas/00-index.md +0 -110
  70. package/livepilot/skills/livepilot-core/references/device-atlas/distortion-and-character.md +0 -687
  71. package/livepilot/skills/livepilot-core/references/device-atlas/drums-and-percussion.md +0 -753
  72. package/livepilot/skills/livepilot-core/references/device-atlas/dynamics-and-punch.md +0 -525
  73. package/livepilot/skills/livepilot-core/references/device-atlas/eq-and-filtering.md +0 -402
  74. package/livepilot/skills/livepilot-core/references/device-atlas/midi-tools.md +0 -963
  75. package/livepilot/skills/livepilot-core/references/device-atlas/movement-and-modulation.md +0 -874
  76. package/livepilot/skills/livepilot-core/references/device-atlas/space-and-depth.md +0 -571
  77. package/livepilot/skills/livepilot-core/references/device-atlas/spectral-and-weird.md +0 -714
  78. package/livepilot/skills/livepilot-core/references/device-atlas/synths-native.md +0 -953
  79. package/livepilot/skills/livepilot-core/references/device-knowledge/00-index.md +0 -34
  80. package/livepilot/skills/livepilot-core/references/device-knowledge/automation-as-music.md +0 -204
  81. package/livepilot/skills/livepilot-core/references/device-knowledge/chains-genre.md +0 -173
  82. package/livepilot/skills/livepilot-core/references/device-knowledge/creative-thinking.md +0 -211
  83. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-distortion.md +0 -188
  84. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-space.md +0 -162
  85. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-spectral.md +0 -229
  86. package/livepilot/skills/livepilot-core/references/device-knowledge/instruments-synths.md +0 -243
  87. package/livepilot/skills/livepilot-core/references/m4l-devices.md +0 -352
  88. package/livepilot/skills/livepilot-core/references/memory-guide.md +0 -107
  89. package/livepilot/skills/livepilot-core/references/midi-recipes.md +0 -402
  90. package/livepilot/skills/livepilot-core/references/mixing-patterns.md +0 -578
  91. package/livepilot/skills/livepilot-core/references/overview.md +0 -290
  92. package/livepilot/skills/livepilot-core/references/sample-manipulation.md +0 -724
  93. package/livepilot/skills/livepilot-core/references/sound-design-deep.md +0 -140
  94. package/livepilot/skills/livepilot-core/references/sound-design.md +0 -393
  95. package/livepilot/skills/livepilot-devices/SKILL.md +0 -169
  96. package/livepilot/skills/livepilot-evaluation/SKILL.md +0 -156
  97. package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +0 -118
  98. package/livepilot/skills/livepilot-evaluation/references/evaluation-contracts.md +0 -121
  99. package/livepilot/skills/livepilot-evaluation/references/memory-promotion.md +0 -110
  100. package/livepilot/skills/livepilot-mix-engine/SKILL.md +0 -123
  101. package/livepilot/skills/livepilot-mix-engine/references/mix-critics.md +0 -143
  102. package/livepilot/skills/livepilot-mix-engine/references/mix-moves.md +0 -105
  103. package/livepilot/skills/livepilot-mixing/SKILL.md +0 -157
  104. package/livepilot/skills/livepilot-notes/SKILL.md +0 -130
  105. package/livepilot/skills/livepilot-performance-engine/SKILL.md +0 -122
  106. package/livepilot/skills/livepilot-performance-engine/references/performance-safety.md +0 -98
  107. package/livepilot/skills/livepilot-release/SKILL.md +0 -130
  108. package/livepilot/skills/livepilot-sample-engine/SKILL.md +0 -105
  109. package/livepilot/skills/livepilot-sample-engine/references/sample-critics.md +0 -87
  110. package/livepilot/skills/livepilot-sample-engine/references/sample-philosophy.md +0 -51
  111. package/livepilot/skills/livepilot-sample-engine/references/sample-techniques.md +0 -131
  112. package/livepilot/skills/livepilot-sound-design-engine/SKILL.md +0 -168
  113. package/livepilot/skills/livepilot-sound-design-engine/references/patch-model.md +0 -119
  114. package/livepilot/skills/livepilot-sound-design-engine/references/sound-design-critics.md +0 -118
  115. package/livepilot/skills/livepilot-wonder/SKILL.md +0 -79
  116. package/m4l_device/LivePilot_Analyzer.amxd.pre-presentation-backup +0 -0
  117. package/m4l_device/LivePilot_Analyzer.maxpat +0 -2705
  118. package/m4l_device/LivePilot_Analyzer.maxproj +0 -53
  119. package/manifest.json +0 -91
  120. package/mcp_server/splice_client/protos/app_pb2.pyi +0 -1153
  121. package/scripts/generate_tool_catalog.py +0 -106
  122. package/scripts/sync_metadata.py +0 -349
@@ -287,11 +287,20 @@ def load_browser_item(song, params):
287
287
  # and use the subcategory or the full fragment for matching
288
288
  if "FileId_" in device_name:
289
289
  # URI contains an internal file ID — name-based search won't work.
290
- # Try one more URI pass with a much higher iteration limit.
290
+ # We fall back to one URI walk, but with a TIGHT iteration budget:
291
+ # this runs synchronously on Ableton's audio/main thread, and the
292
+ # previous 200 000-node walk could stall audio and GUI for several
293
+ # seconds on large libraries (documented in CLAUDE.md).
294
+ #
295
+ # If the item isn't found inside the budget, we return a clean
296
+ # STATE_ERROR pointing the caller at search_browser(), which does
297
+ # the same walk lazily from a cached Python-side index without
298
+ # hogging the audio thread.
291
299
  _iterations[0] = 0
292
- DEEP_MAX = 200000
300
+ DEEP_MAX = 20000 # was 200_000 — 10x reduction
301
+ DEEP_DEPTH_MAX = 8 # was 12 — shallower depth is usually enough
293
302
  def find_by_uri_deep(parent, target_uri, depth=0):
294
- if depth > 12 or _iterations[0] > DEEP_MAX:
303
+ if depth > DEEP_DEPTH_MAX or _iterations[0] > DEEP_MAX:
295
304
  return None
296
305
  try:
297
306
  children = list(parent.children)
@@ -326,9 +335,10 @@ def load_browser_item(song, params):
326
335
  }
327
336
 
328
337
  raise ValueError(
329
- "Item '%s' not found in browser (FileId URI — try "
330
- "search_browser to find the item, then use find_and_load_device "
331
- "with the exact name instead)" % uri
338
+ "Item '%s' not found inside deep-scan budget (FileId URI). "
339
+ "Use search_browser(query=...) to locate it without stalling "
340
+ "Ableton's audio thread, then call load_browser_item with the "
341
+ "returned URI." % uri
332
342
  )
333
343
 
334
344
  for sep in (":", "/"):
@@ -199,17 +199,22 @@ def toggle_device(song, params):
199
199
  track = get_track(song, track_index)
200
200
  device = get_device(track, device_index)
201
201
 
202
- # Find the "Device On" parameter by name (safer than assuming index 0)
202
+ # Find the "Device On" parameter by name the previous fallback
203
+ # blindly assumed parameters[0] was an on/off switch, which for many
204
+ # devices is actually "Filter Frequency", "Gain", or similar. The
205
+ # fallback silently mutated an arbitrary parameter while reporting
206
+ # is_active as if toggling had worked. Now refuse to guess.
203
207
  on_param = None
204
208
  for p in device.parameters:
205
209
  if p.name == "Device On":
206
210
  on_param = p
207
211
  break
208
212
  if on_param is None:
209
- # Fallback to parameter 0 for devices that don't use "Device On"
210
- if not list(device.parameters):
211
- raise ValueError("Device '%s' has no parameters to toggle" % device.name)
212
- on_param = device.parameters[0]
213
+ raise ValueError(
214
+ "Device '%s' exposes no 'Device On' parameter and cannot be "
215
+ "toggled programmatically. Use delete_device or disable it "
216
+ "through the UI." % device.name
217
+ )
213
218
 
214
219
  on_param.value = 1.0 if active else 0.0
215
220
  return {"name": device.name, "is_active": on_param.value > 0.5}
@@ -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"])
@@ -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 += data.decode("utf-8", errors="replace")
209
- if len(buf) > 4 * 1024 * 1024: # 4 MB
217
+ buf.extend(data)
218
+ if len(buf) > MAX_BUF:
210
219
  self._log("Client buffer overflow — disconnecting")
211
220
  break
212
- while "\n" in buf:
213
- line, buf = buf.split("\n", 1)
214
- line = line.strip()
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
- try:
259
- self._command_queue.get_nowait()
260
- except queue.Empty:
261
- pass
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
- Falls back to (12, 0, 0) if detection fails.
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
- _cached_version = (12, 0, 0)
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 — 323 tools, 45 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 — 323 tools, 45 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.7",
14
- "author": {
15
- "name": "Pilot Studio"
16
- },
17
- "source": "./livepilot",
18
- "category": "integration"
19
- }
20
- ]
21
- }
@@ -1,9 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "livepilot": {
4
- "command": "node",
5
- "args": ["bin/livepilot.js"],
6
- "cwd": "/Users/visansilviugeorge/Desktop/DREAM AI/LivePilot"
7
- }
8
- }
9
- }
package/.mcpbignore DELETED
@@ -1,60 +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
- # Local .amxd backups from re-freeze / rollback sessions
28
- m4l_device/*.pre-*-backup
29
-
30
- # Credentials and tokens
31
- .mcpregistry_*
32
- .env
33
- .npmrc
34
-
35
- # Docs and marketing (not needed at runtime)
36
- # Ship only docs/manual/, docs/assets/, docs/M4L_BRIDGE.md, docs/TOOL_REFERENCE.md
37
- docs/specs/
38
- docs/superpowers/
39
- docs/plans/
40
- docs/research/
41
- docs/v2-master-spec/
42
- docs/LivePilot-1.7-Perception/
43
- docs/2026-*
44
- docs/AGENT_OS_V1.md
45
- docs/COMPOSITION_ENGINE_V1.md
46
- docs/ableton-library-map.md
47
- docs/patreon-content.md
48
- docs/social-banner.*
49
- docs/screenshots/
50
-
51
- # Large binary already in User Library after install
52
- # m4l_device/LivePilot_Analyzer.amxd
53
-
54
- # Dev config (root-level only — keep livepilot/.mcp.json which the plugin needs)
55
- /.mcp.json
56
- .npmignore
57
- .editorconfig
58
- CODE_OF_CONDUCT.md
59
- CONTRIBUTING.md
60
- SECURITY.md
package/AGENTS.md DELETED
@@ -1,46 +0,0 @@
1
- # LivePilot v1.10.7 — 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
- - 323 tools across 45 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, experiment, musical_intelligence, semantic_moves
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 323 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