livepilot 1.27.2 → 1.27.3
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 +66 -0
- package/README.md +10 -7
- package/bin/livepilot.js +97 -39
- package/livepilot/.Codex-plugin/plugin.json +1 -1
- package/livepilot/.claude-plugin/plugin.json +1 -1
- package/livepilot/skills/livepilot-core/SKILL.md +33 -1
- package/livepilot/skills/livepilot-core/references/atlas-tool-notes.md +69 -0
- package/livepilot/skills/livepilot-core/references/overview.md +18 -11
- package/livepilot/skills/livepilot-core/references/perception.md +125 -0
- package/livepilot/skills/livepilot-devices/references/device-parameter-units.md +66 -0
- package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +1 -1
- package/livepilot/skills/livepilot-mix-engine/SKILL.md +8 -0
- package/livepilot/skills/livepilot-release/SKILL.md +1 -1
- package/livepilot/skills/livepilot-sample-engine/references/splice-tools-notes.md +56 -0
- package/livepilot/skills/livepilot-wonder/SKILL.md +6 -0
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/m4l_device/livepilot_bridge.js +1 -1
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/atlas/__init__.py +181 -40
- package/mcp_server/atlas/overlays.py +46 -3
- package/mcp_server/atlas/tools.py +226 -86
- package/mcp_server/audit/checks.py +50 -22
- package/mcp_server/audit/state.py +10 -2
- package/mcp_server/audit/tools.py +27 -6
- package/mcp_server/composer/develop/apply.py +7 -7
- package/mcp_server/composer/fast/apply.py +29 -23
- package/mcp_server/composer/framework/atlas_resolver.py +16 -1
- package/mcp_server/composer/full/apply.py +40 -34
- package/mcp_server/composer/full/engine.py +66 -32
- package/mcp_server/composer/tools.py +4 -3
- package/mcp_server/connection.py +67 -9
- package/mcp_server/creative_constraints/engine.py +10 -2
- package/mcp_server/creative_constraints/tools.py +24 -7
- package/mcp_server/curves.py +30 -7
- package/mcp_server/device_forge/builder.py +40 -11
- package/mcp_server/device_forge/models.py +9 -0
- package/mcp_server/device_forge/tools.py +30 -11
- package/mcp_server/experiment/engine.py +29 -22
- package/mcp_server/experiment/tools.py +15 -5
- package/mcp_server/m4l_bridge.py +69 -7
- package/mcp_server/memory/taste_graph.py +43 -0
- package/mcp_server/memory/technique_store.py +26 -3
- package/mcp_server/memory/tools.py +62 -4
- package/mcp_server/mix_engine/critics.py +187 -30
- package/mcp_server/mix_engine/models.py +21 -1
- package/mcp_server/mix_engine/state_builder.py +87 -8
- package/mcp_server/mix_engine/tools.py +16 -4
- package/mcp_server/performance_engine/tools.py +56 -8
- package/mcp_server/persistence/base_store.py +11 -0
- package/mcp_server/persistence/project_store.py +132 -8
- package/mcp_server/persistence/taste_store.py +90 -7
- package/mcp_server/preview_studio/engine.py +40 -10
- package/mcp_server/preview_studio/models.py +40 -0
- package/mcp_server/preview_studio/tools.py +56 -12
- package/mcp_server/project_brain/arrangement_graph.py +4 -0
- package/mcp_server/project_brain/models.py +2 -0
- package/mcp_server/project_brain/role_graph.py +13 -7
- package/mcp_server/reference_engine/gap_analyzer.py +58 -3
- package/mcp_server/reference_engine/profile_builder.py +47 -4
- package/mcp_server/reference_engine/tools.py +6 -0
- package/mcp_server/runtime/execution_router.py +51 -1
- package/mcp_server/runtime/tools.py +0 -1
- package/mcp_server/sample_engine/sources.py +0 -2
- package/mcp_server/sample_engine/tools.py +19 -38
- package/mcp_server/semantic_moves/mix_compilers.py +276 -51
- package/mcp_server/semantic_moves/performance_compilers.py +51 -17
- package/mcp_server/semantic_moves/resolvers.py +45 -0
- package/mcp_server/semantic_moves/sound_design_compilers.py +14 -6
- package/mcp_server/semantic_moves/tools.py +80 -2
- package/mcp_server/semantic_moves/transition_compilers.py +26 -9
- package/mcp_server/server.py +26 -24
- package/mcp_server/session_continuity/tracker.py +51 -3
- package/mcp_server/song_brain/builder.py +47 -5
- package/mcp_server/song_brain/tools.py +21 -7
- package/mcp_server/sound_design/critics.py +1 -0
- package/mcp_server/splice_client/client.py +117 -33
- package/mcp_server/splice_client/http_bridge.py +15 -3
- package/mcp_server/splice_client/quota.py +28 -0
- package/mcp_server/stuckness_detector/detector.py +8 -5
- package/mcp_server/synthesis_brain/adapters/drift.py +13 -0
- package/mcp_server/synthesis_brain/adapters/meld.py +13 -0
- package/mcp_server/tools/_analyzer_engine/sample.py +36 -10
- package/mcp_server/tools/_perception_engine.py +6 -0
- package/mcp_server/tools/agent_os.py +4 -1
- package/mcp_server/tools/analyzer.py +198 -209
- package/mcp_server/tools/arrangement.py +7 -4
- package/mcp_server/tools/automation.py +24 -4
- package/mcp_server/tools/browser.py +25 -11
- package/mcp_server/tools/clips.py +6 -0
- package/mcp_server/tools/composition.py +33 -2
- package/mcp_server/tools/devices.py +53 -53
- package/mcp_server/tools/generative.py +14 -14
- package/mcp_server/tools/harmony.py +7 -7
- package/mcp_server/tools/mixing.py +4 -4
- package/mcp_server/tools/planner.py +68 -6
- package/mcp_server/tools/research.py +20 -2
- package/mcp_server/tools/theory.py +10 -10
- package/mcp_server/tools/transport.py +7 -2
- package/mcp_server/transition_engine/critics.py +13 -1
- package/mcp_server/user_corpus/tools.py +30 -1
- package/mcp_server/wonder_mode/engine.py +82 -9
- package/mcp_server/wonder_mode/session.py +32 -10
- package/mcp_server/wonder_mode/tools.py +14 -1
- package/package.json +1 -1
- package/remote_script/LivePilot/__init__.py +1 -1
- package/remote_script/LivePilot/arrangement.py +93 -33
- package/remote_script/LivePilot/browser.py +60 -4
- package/remote_script/LivePilot/devices.py +132 -62
- package/remote_script/LivePilot/mixing.py +31 -5
- package/remote_script/LivePilot/server.py +94 -22
- package/remote_script/LivePilot/transport.py +11 -0
- package/requirements.txt +5 -5
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.27.3 — 2026-07-10
|
|
4
|
+
|
|
5
|
+
Deep-review remediation campaign (2026-07-09, on top of the 2026-06-24 fix batch): event-loop
|
|
6
|
+
blocking eliminated tree-wide, release-pipeline gates hardened, atlas scan truncation fixed,
|
|
7
|
+
Splice connection health, state-layer race/replay guards, docs drift automation, and +262 tests
|
|
8
|
+
(4326 → 4597 passing). No change to the tool surface (467 tools / 56 domains).
|
|
9
|
+
|
|
10
|
+
### Fixed — event loop (systemic)
|
|
11
|
+
- Every remaining blocking call in async tool paths offloaded (~80 sites across 13 files):
|
|
12
|
+
the composer fast/full/develop apply executors, the shared plan-step executor
|
|
13
|
+
(`execution_router._execute_step_async`), preview/experiment paths, analyzer helper call
|
|
14
|
+
sites, automation session-record, agent_os iteration, device-forge/file I/O, and lifespan
|
|
15
|
+
subprocess probes. New canonical wrapper `AbletonConnection.send_command_async()`.
|
|
16
|
+
- The AST regression guard now scans ALL of `mcp_server/` (was analyzer.py-only) with
|
|
17
|
+
one-hop transitive detection and file-I/O/subprocess patterns (`scripts/scan_async_blocking.py`).
|
|
18
|
+
|
|
19
|
+
Live-verified on Ableton 12.4.2 (2026-07-10): per-track volume reporting, force_arrangement
|
|
20
|
+
with return tracks, sidechain name resolution (both casings), analyzer bridge reconnect, and a
|
|
21
|
+
full 40k-device library rescan with zero category truncation.
|
|
22
|
+
|
|
23
|
+
### Fixed — correctness
|
|
24
|
+
- Sidechain source matching gained a case-insensitive EXACT tier (found live: Live 12.4
|
|
25
|
+
routing menus can list bare unprefixed track names, where the "-name" suffix fallback
|
|
26
|
+
never fires); matching ladder extracted into a tested helper.
|
|
27
|
+
- `audit_layer` §5.1 timbre check was a silent double no-op (wrong call signature + uppercase
|
|
28
|
+
band table vs lowercase producers) — now plumbs cached analyzer spectrum and case-folds.
|
|
29
|
+
- Atlas scans no longer truncate alphabetically at 1000 entries/category (drum kits previously
|
|
30
|
+
cut off before reaching most of the alphabet); scans record per-category counts + truncation
|
|
31
|
+
flags, and atlas searches warn when a truncated category is queried. Rescan required to
|
|
32
|
+
rebuild an existing user atlas (`scan_full_library(force=True)`).
|
|
33
|
+
- Semantic mix/sound-design/transition/performance moves now nudge track volume RELATIVE to the
|
|
34
|
+
current level (bounded, direction-safe) instead of writing absolute constants; the Remote
|
|
35
|
+
Script now reports per-track volume in `get_session_info`.
|
|
36
|
+
- Splice client marks itself degraded on RPC failure and self-heals with a one-shot reconnect —
|
|
37
|
+
a Splice desktop restart no longer yields silent fake "0 results" for the session; quota
|
|
38
|
+
check-and-record is atomic; HTTP retry no longer sleeps after the final attempt.
|
|
39
|
+
- Preview/wonder cached plans carry a session fingerprint and refuse commit with STATE_ERROR
|
|
40
|
+
when the session changed shape; shared caches are lock-guarded; persisted taste/project
|
|
41
|
+
stores back up before any version-mismatch reset; `song_brain` ids are content-aware.
|
|
42
|
+
- `get_emotional_arc` harmonic-instability term computed (was structurally zero);
|
|
43
|
+
flucoma probe no longer reports empty dirs as installed; composer engine renumbers layers
|
|
44
|
+
after unresolved-sample drops on the experiment-escalation path.
|
|
45
|
+
|
|
46
|
+
### Changed — release gates & CI
|
|
47
|
+
- New CI jobs: MCPB bundle build (asset previously shipped missing for 4 releases),
|
|
48
|
+
Python 3.11 compatibility for `remote_script/` (compileall + vermin), content-level
|
|
49
|
+
.amxd freeze check (full bridge command set, not just the version string).
|
|
50
|
+
- `bin/livepilot.js` venv staleness keyed on a requirements.txt content hash (hardcoded import
|
|
51
|
+
list had drifted — upgrading users silently never installed the Splice gRPC dependencies).
|
|
52
|
+
- `sync_metadata.py` validates JSON manifests version-field-by-field (caught a live
|
|
53
|
+
server.json split-version); docs Domain Map is now generated from the live registry;
|
|
54
|
+
banner assets and README What's New are drift-guarded.
|
|
55
|
+
|
|
56
|
+
### Changed — performance & analysis quality
|
|
57
|
+
- Server import ~2.0s → ~0.9s (lazy overlay index + libyaml CSafeLoader); atlas duplicate
|
|
58
|
+
warnings throttled; test suite wall-clock ~41s → ~32s.
|
|
59
|
+
- Mix-critic confidence values are data-derived (sample size, measured-vs-heuristic basis,
|
|
60
|
+
margin) instead of hardcoded literals; `analyze_mix`/`get_mix_issues` accept
|
|
61
|
+
`target_style="loud_master"` to suppress the over-compressed flag for intentionally loud
|
|
62
|
+
masters; Wonder Mode ranking surfaces a `boldest_executable` slot alongside the safe pick.
|
|
63
|
+
- Security hardening: corpus plugin-id path validation, loopback-only UDP analyzer ingestion,
|
|
64
|
+
competing-TCP-client identification in eviction errors.
|
|
65
|
+
|
|
66
|
+
### Changed — dependencies
|
|
67
|
+
- **2026-06-25** — Raised the Python floor to 3.12: numpy>=2.5.0 and scipy>=1.18.0 declare `Requires-Python >=3.12`, so the prior 3.11 floor blocked both dependency bumps across the CI matrix. CI now tests only Python 3.12; the install-time Python-version diagnostic and manifest/docs floor references were updated to match. `remote_script/` stays 3.11-syntax-compatible for Ableton's embedded Python (Live 12.3) — the CI matrix change does not relax that constraint.
|
|
68
|
+
|
|
3
69
|
## v1.27.2 — 2026-06-23
|
|
4
70
|
|
|
5
71
|
Maintenance release: M4L bridge response-correlation + chunk-reassembly hardening, plan-routing fixes, a Python 3.11 floor with clearer install diagnostics, and a Remote Script Group-track crash guard. No change to the tool surface (467 tools / 56 domains). Re-frozen LivePilot_Analyzer.amxd (analyzer reports 1.27.2).
|
package/README.md
CHANGED
|
@@ -38,14 +38,17 @@
|
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
## What's New in v1.27.
|
|
41
|
+
## What's New in v1.27.3
|
|
42
42
|
|
|
43
|
-
A
|
|
43
|
+
A deep-review remediation release — ~150 fixes across two audit campaigns, no change to the tool surface (467 tools / 56 domains):
|
|
44
44
|
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
48
|
-
- **Safer
|
|
45
|
+
- **Event-loop blocking eliminated tree-wide** — every remaining blocking call in async tool paths (composer apply executors, the shared plan-step executor, preview/experiment paths, ~80 sites in 13 files) now offloads to a worker thread; a repo-wide AST regression guard keeps it that way. Long composes no longer freeze concurrent tools or the analyzer bridge.
|
|
46
|
+
- **Atlas scans no longer truncate** — library scans previously capped each category at 1,000 entries alphabetically (most drum one-shots were unreachable); the cap is now 25,000 with per-category truncation flags and rescan warnings. Run `scan_full_library(force=True)` once to rebuild your atlas.
|
|
47
|
+
- **Splice self-heals** — a Splice desktop restart no longer silently turns every search into fake "0 results"; the client marks itself degraded and reconnects on the next call.
|
|
48
|
+
- **Safer state** — cached preview/wonder plans carry a session fingerprint and refuse to replay against a session that changed shape; persisted taste/project stores back up before any reset.
|
|
49
|
+
- **Stronger release gates** — the MCPB bundle, .amxd freeze content, and Python 3.11 Remote Script compatibility are now all CI-enforced.
|
|
50
|
+
- **Python 3.12 floor** for the MCP server (numpy ≥2.5 / scipy ≥1.18); the Remote Script stays 3.11-compatible for Ableton's embedded Python.
|
|
51
|
+
- **v1.27.1** fixed 35 issues from a deep audit and restored tools that had silently broken (`augment_with_samples`, `get_composition_plan`, `propose_composer_branches`, `check_clip_key_consistency`, `compare_phrase_renders`), plus recursive installed-plugin scanning.
|
|
49
52
|
- **v1.27.0** added two read-only Live 12.4 capability-probe tools (`probe_link_audio`, `probe_stem_workflow`).
|
|
50
53
|
|
|
51
54
|
Full details in the [CHANGELOG](CHANGELOG.md).
|
|
@@ -751,7 +754,7 @@ npx livepilot --version # Show version
|
|
|
751
754
|
| Requirement | Minimum |
|
|
752
755
|
|-------------|---------|
|
|
753
756
|
| Ableton Live | **12** (any edition). Suite required for Max for Live bridge and stock instruments |
|
|
754
|
-
| Python | 3.
|
|
757
|
+
| Python | 3.12+ (numpy>=2.5 / scipy>=1.18 require Python 3.12) |
|
|
755
758
|
| Node.js | 18+ |
|
|
756
759
|
| OS | macOS / Windows |
|
|
757
760
|
| Splice | Desktop app with downloaded samples (optional — enables SQLite metadata search) |
|
package/bin/livepilot.js
CHANGED
|
@@ -15,12 +15,12 @@ const REQUIREMENTS = path.join(ROOT, "requirements.txt");
|
|
|
15
15
|
// Python detection
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
|
|
18
|
-
// Minimum Python is 3.
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
const MIN_PY_MINOR =
|
|
18
|
+
// Minimum Python is 3.12: numpy>=2.5.0 and scipy>=1.18.0 (see requirements.txt)
|
|
19
|
+
// declare requires-python ">=3.12". An older interpreter passes a looser gate,
|
|
20
|
+
// the venv is created, then `pip install` aborts with a cryptic "no matching
|
|
21
|
+
// distribution" — the exact install failure users hit. Gate here so we fail
|
|
22
|
+
// early with a clear message.
|
|
23
|
+
const MIN_PY_MINOR = 12;
|
|
24
24
|
|
|
25
25
|
function findPython() {
|
|
26
26
|
// On Windows, also try the "py -3" launcher which avoids the
|
|
@@ -47,7 +47,7 @@ function findPython() {
|
|
|
47
47
|
const actualArgs = cmd === "py" ? ["-3"] : [];
|
|
48
48
|
return { cmd: actualCmd, version: out, prefixArgs: actualArgs };
|
|
49
49
|
}
|
|
50
|
-
// Found Python 3 but below 3.
|
|
50
|
+
// Found Python 3 but below 3.12 — remember the newest for diagnostics.
|
|
51
51
|
if (major === 3 && (!tooOld || minor > tooOld.minor)) {
|
|
52
52
|
tooOld = { version: out, minor };
|
|
53
53
|
}
|
|
@@ -122,8 +122,8 @@ function pipInstall(venvPy) {
|
|
|
122
122
|
console.error("");
|
|
123
123
|
console.error("LivePilot: dependency installation failed.");
|
|
124
124
|
if (/No matching distribution|requires-python|Could not find a version/i.test(stderr)) {
|
|
125
|
-
console.error(" Most likely your Python is too old — LivePilot needs Python >= 3.
|
|
126
|
-
console.error(" (numpy/scipy
|
|
125
|
+
console.error(" Most likely your Python is too old — LivePilot needs Python >= 3.12");
|
|
126
|
+
console.error(" (numpy>=2.5 / scipy>=1.18 require Python 3.12). Install 3.12+, delete the");
|
|
127
127
|
console.error(" .venv folder, and retry.");
|
|
128
128
|
}
|
|
129
129
|
const tail = stderr.split("\n").filter(Boolean).slice(-12);
|
|
@@ -136,6 +136,48 @@ function pipInstall(venvPy) {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Content hash of requirements.txt — the venv staleness signal.
|
|
141
|
+
*
|
|
142
|
+
* The previous check was a hardcoded import list that silently drifted from
|
|
143
|
+
* requirements.txt (grpcio/protobuf were added for the Splice gRPC surface
|
|
144
|
+
* but never joined the list, so upgrading users kept a venv without them and
|
|
145
|
+
* the feature silently disabled itself). Hashing the file makes staleness
|
|
146
|
+
* detection automatically correct for every future dependency change.
|
|
147
|
+
*/
|
|
148
|
+
function requirementsHash() {
|
|
149
|
+
const crypto = require("crypto");
|
|
150
|
+
const reqs = fs.readFileSync(path.join(ROOT, "requirements.txt"));
|
|
151
|
+
return crypto.createHash("sha256").update(reqs).digest("hex");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function venvStampPath() {
|
|
155
|
+
return path.join(ROOT, VENV_DIR, ".requirements-sha256");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function writeVenvStamp() {
|
|
159
|
+
try {
|
|
160
|
+
fs.writeFileSync(venvStampPath(), requirementsHash() + "\n");
|
|
161
|
+
} catch {
|
|
162
|
+
// Non-fatal: worst case the next run reinstalls.
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Pure decision function for venv staleness — extracted from ensureVenv so
|
|
168
|
+
* the reinstall/reuse/create branching can be unit-tested without touching
|
|
169
|
+
* the filesystem or spawning pip/venv. Behavior-identical to the inline
|
|
170
|
+
* logic it replaces:
|
|
171
|
+
* - no venv on disk -> "create"
|
|
172
|
+
* - venv exists, stamp matches hash -> "reuse"
|
|
173
|
+
* - venv exists, stamp missing/mismatched -> "update"
|
|
174
|
+
*/
|
|
175
|
+
function decideVenvAction(venvExists, storedStamp, currentHash) {
|
|
176
|
+
if (!venvExists) return "create";
|
|
177
|
+
if (storedStamp === currentHash) return "reuse";
|
|
178
|
+
return "update";
|
|
179
|
+
}
|
|
180
|
+
|
|
139
181
|
/**
|
|
140
182
|
* Ensure a local .venv exists with dependencies installed.
|
|
141
183
|
* Returns the path to the venv Python binary.
|
|
@@ -143,25 +185,31 @@ function pipInstall(venvPy) {
|
|
|
143
185
|
function ensureVenv(systemPython, prefixArgs) {
|
|
144
186
|
const prefix = prefixArgs || [];
|
|
145
187
|
const venvPy = venvPython();
|
|
188
|
+
const venvExists = fs.existsSync(venvPy);
|
|
146
189
|
|
|
147
|
-
|
|
148
|
-
if (
|
|
190
|
+
let stamp = null;
|
|
191
|
+
if (venvExists) {
|
|
149
192
|
try {
|
|
150
|
-
|
|
151
|
-
encoding: "utf-8",
|
|
152
|
-
timeout: 10000,
|
|
153
|
-
stdio: "pipe",
|
|
154
|
-
});
|
|
155
|
-
return venvPy; // venv exists and all deps importable
|
|
193
|
+
stamp = fs.readFileSync(venvStampPath(), "utf-8").trim();
|
|
156
194
|
} catch {
|
|
157
|
-
// venv
|
|
158
|
-
console.error("LivePilot: reinstalling Python dependencies...");
|
|
159
|
-
pipInstall(venvPy);
|
|
160
|
-
return venvPy;
|
|
195
|
+
stamp = null; // pre-hash venv (or stamp deleted) — verify by reinstall
|
|
161
196
|
}
|
|
162
197
|
}
|
|
163
198
|
|
|
164
|
-
|
|
199
|
+
const action = decideVenvAction(venvExists, stamp, requirementsHash());
|
|
200
|
+
|
|
201
|
+
if (action === "reuse") {
|
|
202
|
+
return venvPy; // venv exists and was installed from this exact requirements.txt
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (action === "update") {
|
|
206
|
+
console.error("LivePilot: requirements changed — updating Python dependencies...");
|
|
207
|
+
pipInstall(venvPy);
|
|
208
|
+
writeVenvStamp();
|
|
209
|
+
return venvPy;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// action === "create"
|
|
165
213
|
console.error("LivePilot: setting up Python environment (first run)...");
|
|
166
214
|
execFileSync(systemPython, [...prefix, "-m", "venv", VENV_DIR], {
|
|
167
215
|
cwd: ROOT,
|
|
@@ -171,6 +219,7 @@ function ensureVenv(systemPython, prefixArgs) {
|
|
|
171
219
|
|
|
172
220
|
console.error("LivePilot: installing dependencies...");
|
|
173
221
|
pipInstall(venvPython());
|
|
222
|
+
writeVenvStamp();
|
|
174
223
|
|
|
175
224
|
return venvPython();
|
|
176
225
|
}
|
|
@@ -309,12 +358,12 @@ async function doctor() {
|
|
|
309
358
|
if (pyInfo && !pyInfo.tooOld) {
|
|
310
359
|
console.log(" Python: %s (%s)", pyInfo.version, pyInfo.cmd);
|
|
311
360
|
} else if (pyInfo && pyInfo.tooOld) {
|
|
312
|
-
console.log(" Python: %s found, but LivePilot needs >= 3.
|
|
313
|
-
console.log(" Fix: install Python 3.
|
|
361
|
+
console.log(" Python: %s found, but LivePilot needs >= 3.12", pyInfo.version);
|
|
362
|
+
console.log(" Fix: install Python 3.12+ (numpy>=2.5 / scipy>=1.18 require Python 3.12)");
|
|
314
363
|
ok = false;
|
|
315
364
|
} else {
|
|
316
|
-
console.log(" Python: NOT FOUND (need >= 3.
|
|
317
|
-
console.log(" Fix: install Python 3.
|
|
365
|
+
console.log(" Python: NOT FOUND (need >= 3.12)");
|
|
366
|
+
console.log(" Fix: install Python 3.12+ and add to PATH");
|
|
318
367
|
ok = false;
|
|
319
368
|
}
|
|
320
369
|
|
|
@@ -737,12 +786,12 @@ async function setup() {
|
|
|
737
786
|
if (pyInfo && !pyInfo.tooOld) {
|
|
738
787
|
console.log(" ✓ %s", pyInfo.version);
|
|
739
788
|
} else if (pyInfo && pyInfo.tooOld) {
|
|
740
|
-
console.log(" ✗ %s found, but LivePilot needs Python >= 3.
|
|
741
|
-
console.log(" (numpy/scipy
|
|
789
|
+
console.log(" ✗ %s found, but LivePilot needs Python >= 3.12", pyInfo.version);
|
|
790
|
+
console.log(" (numpy>=2.5 / scipy>=1.18 require Python 3.12 — pip would fail)");
|
|
742
791
|
console.log(" Install: brew install python@3.12 (macOS) or python.org (Windows)");
|
|
743
792
|
ok = false;
|
|
744
793
|
} else {
|
|
745
|
-
console.log(" ✗ Python >= 3.
|
|
794
|
+
console.log(" ✗ Python >= 3.12 not found");
|
|
746
795
|
console.log(" Install: brew install python@3.12 (macOS) or python.org (Windows)");
|
|
747
796
|
ok = false;
|
|
748
797
|
}
|
|
@@ -784,7 +833,7 @@ async function setup() {
|
|
|
784
833
|
ok = false;
|
|
785
834
|
}
|
|
786
835
|
} else if (pyInfo && pyInfo.tooOld) {
|
|
787
|
-
console.log(" ⊘ Skipped (%s found, need Python >= 3.
|
|
836
|
+
console.log(" ⊘ Skipped (%s found, need Python >= 3.12)", pyInfo.version);
|
|
788
837
|
} else {
|
|
789
838
|
console.log(" ⊘ Skipped (no Python)");
|
|
790
839
|
}
|
|
@@ -974,12 +1023,12 @@ async function main() {
|
|
|
974
1023
|
const pyInfo = findPython();
|
|
975
1024
|
if (!pyInfo || pyInfo.tooOld) {
|
|
976
1025
|
if (pyInfo && pyInfo.tooOld) {
|
|
977
|
-
console.error("Error: found %s, but LivePilot requires Python >= 3.
|
|
978
|
-
console.error(" numpy>=2.
|
|
979
|
-
console.error(" so dependency installation would fail. Install Python 3.
|
|
1026
|
+
console.error("Error: found %s, but LivePilot requires Python >= 3.12.", pyInfo.version);
|
|
1027
|
+
console.error(" numpy>=2.5.0 and scipy>=1.18.0 require Python >= 3.12,");
|
|
1028
|
+
console.error(" so dependency installation would fail. Install Python 3.12 or newer.");
|
|
980
1029
|
} else {
|
|
981
|
-
console.error("Error: Python >= 3.
|
|
982
|
-
console.error(" Install Python 3.
|
|
1030
|
+
console.error("Error: Python >= 3.12 is required but was not found.");
|
|
1031
|
+
console.error(" Install Python 3.12+ and ensure 'python3' or 'python' is on your PATH.");
|
|
983
1032
|
}
|
|
984
1033
|
console.error("");
|
|
985
1034
|
console.error(" macOS: brew install python@3.12");
|
|
@@ -1026,7 +1075,16 @@ async function main() {
|
|
|
1026
1075
|
});
|
|
1027
1076
|
}
|
|
1028
1077
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1078
|
+
// Only auto-run the CLI when this file is executed directly (`node
|
|
1079
|
+
// bin/livepilot.js ...` or `npx livepilot ...`). When `require()`d as a
|
|
1080
|
+
// module — e.g. from tests exercising `decideVenvAction` in isolation —
|
|
1081
|
+
// skip the side-effecting entrypoint. Behavior-identical for real CLI
|
|
1082
|
+
// invocations; this guard only matters when the file is `require()`d.
|
|
1083
|
+
if (require.main === module) {
|
|
1084
|
+
main().catch((err) => {
|
|
1085
|
+
console.error(err);
|
|
1086
|
+
process.exit(1);
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
module.exports = { decideVenvAction, requirementsHash, venvStampPath };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.3",
|
|
4
4
|
"description": "Agentic production system for Ableton Live 12 \u2014 467 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, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pilot Studio"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.3",
|
|
4
4
|
"description": "Agentic production system for Ableton Live 12 \u2014 467 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, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pilot Studio"
|
|
@@ -47,7 +47,7 @@ Agentic production system for Ableton Live 12. 467 tools across 56 domains, thre
|
|
|
47
47
|
- **Parameter ranges are NOT always 0-1.** Auto Filter Frequency is 20-135. Bit Depth is 1-16. Always read `value_string` to see actual units.
|
|
48
48
|
16. **NEVER apply automation recipes without understanding the target parameter's range** — recipes generate 0-1 curves that get auto-scaled for device parameters, but always verify the result
|
|
49
49
|
17. **LivePilot_Analyzer must be LAST on master chain** — always place after ALL effects (EQ, Compressor, Utility, etc.) so it measures the final post-processing output, not the raw signal. When loading effects on master, either load them before the analyzer or move the analyzer to end afterward
|
|
50
|
-
18. **Remote Script reload workflow** — after any edit to `remote_script/LivePilot/*.py`:
|
|
50
|
+
18. **Remote Script reload workflow** — after any edit to `remote_script/LivePilot/*.py`: install, then call `reload_handlers` (MCP tool, domain: diagnostics). From a LOCAL CHECKOUT the install command is `node bin/livepilot.js --install` — `npx livepilot --install` fetches the PUBLISHED npm package and overwrites local edits with stale code. Use `npx livepilot --install` only for the published package (end-user installs). Either way, NOT `node installer/install.js` — that raw file only module-exports the install function and silently no-ops as a script. NEVER instruct the user to toggle the Control Surface in Live Preferences. The tool uses pkgutil + importlib to re-fire `@register` decorators in-place in <1s while the TCP connection stays open. Standard procedure for every handler change — not just releases
|
|
51
51
|
|
|
52
52
|
## Tool Speed Tiers
|
|
53
53
|
|
|
@@ -79,6 +79,38 @@ Report ALL errors to the user immediately. Common failure modes:
|
|
|
79
79
|
- **M4L Analyzer not connected** — if `get_master_spectrum` errors with "Analyzer not detected", call `ensure_analyzer_on_master`. If it returns `install_required`, call `install_m4l_device(source_path="<repo>/m4l_device/LivePilot_Analyzer.amxd")` and retry. If it errors with "UDP bridge not connected", try `reconnect_bridge` first
|
|
80
80
|
- **Another client connected** — Remote Script only accepts one TCP client on port 9878. If you see this error, the MCP server is already connected. Use MCP tools instead of raw TCP
|
|
81
81
|
|
|
82
|
+
## Response Fields You Must Check
|
|
83
|
+
|
|
84
|
+
These fields were added to existing tool responses. They aren't optional
|
|
85
|
+
extras — each one changes what you're allowed to claim to the user.
|
|
86
|
+
|
|
87
|
+
- **`degraded_reason`** (`enter_wonder_mode` / Wonder Mode) — non-empty when
|
|
88
|
+
fewer than 3 of the returned variants are actually executable, or when no
|
|
89
|
+
matching moves were found and variants are cold-start fallbacks. Contract:
|
|
90
|
+
if `degraded_reason` is set, do NOT present the set as "three genuinely
|
|
91
|
+
different options" — disclose the degradation honestly. See
|
|
92
|
+
`livepilot-wonder`.
|
|
93
|
+
- **`unenforced_constraints`** (`apply_creative_constraint_set` / Creative
|
|
94
|
+
Constraints) — lists constraint names that are advisory-only; the engine
|
|
95
|
+
cannot mechanically verify them against compiled steps. Contract: for every
|
|
96
|
+
name in this list, YOU must self-police that constraint manually — the
|
|
97
|
+
tool returning `valid: true` does not mean an advisory constraint wasn't
|
|
98
|
+
violated.
|
|
99
|
+
- **`measured` / `severity_basis`** (`get_masking_report` / Mix Engine) — a
|
|
100
|
+
masking entry's `severity` is either a real per-track spectral-overlap
|
|
101
|
+
measurement (`measured=True`, `severity_basis="spectral_overlap"`) or a
|
|
102
|
+
role-pair heuristic constant (`measured=False`,
|
|
103
|
+
`severity_basis="role_heuristic"`). Contract: treat `measured=False`
|
|
104
|
+
entries as low-confidence priors, not verified problems — solo the tracks
|
|
105
|
+
and read `get_master_spectrum` before taking a mixing action based on them
|
|
106
|
+
(§3 Analysis Before Action). See `livepilot-mix-engine`.
|
|
107
|
+
- **`load_via` / `browse_hint`** (Atlas — `atlas_search`, `atlas_suggest`,
|
|
108
|
+
`atlas_device_info`, etc.) — set when an atlas entry's `uri` is cleared
|
|
109
|
+
because it's a known-broken M4L pack-instrument reference. Contract: when
|
|
110
|
+
`load_via == "preset"`, do NOT call `load_browser_item` with the atlas
|
|
111
|
+
`uri` (it's empty/invalid) — call `search_browser` with `browse_hint`
|
|
112
|
+
instead to resolve a real URI first.
|
|
113
|
+
|
|
82
114
|
## Technique Memory
|
|
83
115
|
|
|
84
116
|
Three modes:
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Atlas Tool Notes
|
|
2
|
+
|
|
3
|
+
Implementation history and rationale for `mcp_server/atlas/tools.py`
|
|
4
|
+
tools. The tool docstrings carry the operational contract (params,
|
|
5
|
+
return shape, behavior); this file carries the bug history and
|
|
6
|
+
step-by-step internals that explain *why* a tool behaves a certain way,
|
|
7
|
+
for when that context is actually needed.
|
|
8
|
+
|
|
9
|
+
## `scan_full_library` — scan cap history
|
|
10
|
+
|
|
11
|
+
`max_per_category` defaults to 25000, matching the remote script's own
|
|
12
|
+
default. The original hardcoded 1000 cap silently truncated large
|
|
13
|
+
categories in browser-tree (alphabetical) order — e.g. `drum_kits`
|
|
14
|
+
stopped at "Crash" (0 kicks, 2 hats), and the `samples` category alone
|
|
15
|
+
has ~22,000 items per the browser tree, so a "1000 samples" count was
|
|
16
|
+
wrong by a factor of 22 (BUG-2026-04-22#12). Raise the cap further for
|
|
17
|
+
even bigger libraries; lower it for fast smoke scans.
|
|
18
|
+
|
|
19
|
+
`truncated_categories` / `stats.category_truncated` are persisted into
|
|
20
|
+
`device_atlas.json` so `AtlasManager` can warn future
|
|
21
|
+
`atlas_search`/`atlas_suggest` calls that touch a truncated category
|
|
22
|
+
without requiring a fresh scan first (P3-47).
|
|
23
|
+
|
|
24
|
+
Scans always write to the user atlas path
|
|
25
|
+
(`~/.livepilot/atlas/device_atlas.json`), never the bundled baseline —
|
|
26
|
+
this keeps personal inventories (packs, user_library, plugins) out of
|
|
27
|
+
the repo and surviving npm updates (v1.22.0). Enrichments are still
|
|
28
|
+
read from the bundled package.
|
|
29
|
+
|
|
30
|
+
## `atlas_describe_chain` — internals
|
|
31
|
+
|
|
32
|
+
Free-text → chain proposal pipeline, mirroring `splice_describe_sound`
|
|
33
|
+
for the device library (`atlas_chain_suggest` is the structured-input
|
|
34
|
+
sibling — role + genre instead of a sentence):
|
|
35
|
+
|
|
36
|
+
1. Parse role hints from the description (bass/lead/pad/keys/
|
|
37
|
+
percussion/drums/vocal/fx keyword buckets)
|
|
38
|
+
2. Parse aesthetic hints — artist names map to genre/character tags
|
|
39
|
+
(cross-reference `artist-vocabularies.md`), plus explicit genre
|
|
40
|
+
names and character words (warm/cold/bright/dark/lush/...)
|
|
41
|
+
3. Search the atlas (factory + user overlay namespaces) with those terms
|
|
42
|
+
4. Propose the top devices per role with brief rationale, then take the
|
|
43
|
+
top suggestion per role as a simple ordered `chain_proposal`
|
|
44
|
+
|
|
45
|
+
Does not autoload anything — the caller reviews/adjusts, then executes
|
|
46
|
+
via `load_browser_item` + effects.
|
|
47
|
+
|
|
48
|
+
## `atlas_techniques_for_device` — index
|
|
49
|
+
|
|
50
|
+
Backed by the reverse-index file `device_techniques_index.json`
|
|
51
|
+
(auto-generated from the knowledge base — regenerate via the
|
|
52
|
+
post-v1.17 reverse-index builder script when adding new techniques;
|
|
53
|
+
rare, since most additions happen through enrichment YAMLs that the
|
|
54
|
+
index reads directly). `kind` values: `signature_technique` (from the
|
|
55
|
+
device's own atlas entry), `sample_technique` (from
|
|
56
|
+
`sample-techniques.md`), `sound_design_principle` (from
|
|
57
|
+
`sound-design-deep.md`).
|
|
58
|
+
|
|
59
|
+
## `atlas_search` — overlay budget split
|
|
60
|
+
|
|
61
|
+
Searches both the bundled factory atlas (5,264 devices / 33 packs) and
|
|
62
|
+
the user-local overlay corpus (`~/.livepilot/atlas-overlays/` — user-
|
|
63
|
+
scanned Max devices, racks, plugin presets, AI-synthesized plugin
|
|
64
|
+
identity YAMLs). When both sources have hits, `limit` splits roughly
|
|
65
|
+
50/50 (factory gets the rounding-up extra slot); a source with zero
|
|
66
|
+
hits doesn't consume budget. M4L pack instruments occasionally carry a
|
|
67
|
+
bogus `query:Synths#` URI in the atlas — `atlas_search` clears it and
|
|
68
|
+
surfaces a `browse_hint` so callers don't hit `INVALID_PARAM` from
|
|
69
|
+
`load_browser_item` (LIVE#3).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# LivePilot v1.27.
|
|
1
|
+
# LivePilot v1.27.3 — Architecture & Tool Reference
|
|
2
2
|
|
|
3
3
|
Agentic production system for Ableton Live 12. 467 tools across 56 domains. Device atlas (5264 devices, 120 enriched, 47 with aesthetic-tagged `signature_techniques`), spectral perception (M4L analyzer with 9-band FFT — sub_low / sub / low / low_mid / mid / high_mid / high / presence / air), technique memory, automation intelligence (16 curve types, 15 recipes), music theory (Krumhansl-Schmuckler, species counterpoint), generative algorithms (Euclidean rhythm, tintinnabuli, phase shift, additive process), neo-Riemannian harmony (PRL transforms, Tonnetz), MIDI file I/O, **LIVE Splice describe-a-sound + variations via captured GraphQL endpoints (v1.17)**, drum-rack pad-by-pad construction, live dead-device detection via meter sampling, role-aware Simpler defaults, session-record arrangement-automation workaround.
|
|
4
4
|
|
|
@@ -44,9 +44,16 @@ A flat tool list lets the AI press buttons. LivePilot's three layers give it con
|
|
|
44
44
|
|
|
45
45
|
This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spectrum to confirm the mud is actually reduced."
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Core-Domain Reference (~228 tools, 13 of 56 domains)
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
This section documents the 13 highest-traffic domains in prose (what each
|
|
50
|
+
tool does, when to reach for it). It is intentionally NOT exhaustive — the
|
|
51
|
+
remaining domains (sample_engine, atlas, agent_os, wonder_mode, and the rest
|
|
52
|
+
of the Creative Intelligence layer) are covered by their own domain skills
|
|
53
|
+
and by the auto-generated **[Tool Catalog](../../../../docs/manual/tool-catalog.md)**,
|
|
54
|
+
which lists all 467 tools across all 56 domains.
|
|
55
|
+
|
|
56
|
+
### Transport (showing 12 of 21) — Playback, tempo, global state, diagnostics
|
|
50
57
|
|
|
51
58
|
| Tool | What it does | Key params |
|
|
52
59
|
|------|-------------|------------|
|
|
@@ -63,7 +70,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
63
70
|
| `get_recent_actions` | Returns log of recent commands sent to Ableton (newest first) | `limit` (1-50, default 20) |
|
|
64
71
|
| `get_session_diagnostics` | Analyzes session for issues: armed tracks, solo leftovers, unnamed tracks, empty clips | — |
|
|
65
72
|
|
|
66
|
-
### Tracks (14) — Create, delete, configure, group tracks
|
|
73
|
+
### Tracks (showing 14 of 21) — Create, delete, configure, group tracks
|
|
67
74
|
|
|
68
75
|
| Tool | What it does | Key params |
|
|
69
76
|
|------|-------------|------------|
|
|
@@ -82,7 +89,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
82
89
|
| `set_group_fold` | Folds/unfolds a group track | `track_index`, `folded` (bool) |
|
|
83
90
|
| `set_track_input_monitoring` | Sets input monitoring state | `track_index`, `state` (0=In, 1=Auto, 2=Off) |
|
|
84
91
|
|
|
85
|
-
### Clips (11) — Clip lifecycle, properties, warp
|
|
92
|
+
### Clips (showing 11 of 16) — Clip lifecycle, properties, warp
|
|
86
93
|
|
|
87
94
|
| Tool | What it does | Key params |
|
|
88
95
|
|------|-------------|------------|
|
|
@@ -122,7 +129,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
122
129
|
- `velocity_deviation` — -127.0 to 127.0
|
|
123
130
|
- `release_velocity` — 0.0-127.0
|
|
124
131
|
|
|
125
|
-
### Devices (15) — Instruments, effects, racks, 12.3+ device insertion
|
|
132
|
+
### Devices (showing 15 of 42) — Instruments, effects, racks, 12.3+ device insertion
|
|
126
133
|
|
|
127
134
|
| Tool | What it does | Key params |
|
|
128
135
|
|------|-------------|------------|
|
|
@@ -142,7 +149,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
142
149
|
| `set_chain_volume` | Sets volume of a rack chain | `track_index`, `device_index`, `chain_index`, `volume` |
|
|
143
150
|
| `get_device_presets` | Lists presets for a device (audio effects, instruments, MIDI effects) | `device_name` |
|
|
144
151
|
|
|
145
|
-
### Scenes (8) — Scene management
|
|
152
|
+
### Scenes (showing 8 of 12) — Scene management
|
|
146
153
|
|
|
147
154
|
| Tool | What it does | Key params |
|
|
148
155
|
|------|-------------|------------|
|
|
@@ -180,7 +187,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
180
187
|
| `search_browser` | Searches the browser | `query` |
|
|
181
188
|
| `load_browser_item` | Loads a browser item onto a track — **`uri` MUST come from `search_browser` results, NEVER invented** | `track_index`, `uri` |
|
|
182
189
|
|
|
183
|
-
### Arrangement (20) — Timeline, recording, cue points, arrangement notes
|
|
190
|
+
### Arrangement (showing 20 of 21) — Timeline, recording, cue points, arrangement notes
|
|
184
191
|
|
|
185
192
|
| Tool | What it does | Key params |
|
|
186
193
|
|------|-------------|------------|
|
|
@@ -205,7 +212,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
205
212
|
| `jump_to_cue` | Jumps to a cue point by index | `cue_index` |
|
|
206
213
|
| `toggle_cue_point` | Creates/removes cue point at current position | — |
|
|
207
214
|
|
|
208
|
-
### Memory (8) — Technique library persistence
|
|
215
|
+
### Memory (showing 8 of 18) — Technique library persistence
|
|
209
216
|
|
|
210
217
|
| Tool | What it does | Key params |
|
|
211
218
|
|------|-------------|------------|
|
|
@@ -218,7 +225,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
218
225
|
| `memory_update` | Updates name, tags, or qualities | `technique_id`, `name`, `tags`, `qualities` |
|
|
219
226
|
| `memory_delete` | Removes technique (backs up first) | `technique_id` |
|
|
220
227
|
|
|
221
|
-
### Analyzer (38) — Real-time DSP analysis (requires LivePilot Analyzer M4L device on master track)
|
|
228
|
+
### Analyzer (showing 20 of 38) — Real-time DSP analysis (requires LivePilot Analyzer M4L device on master track)
|
|
222
229
|
|
|
223
230
|
| Tool | What it does | Key params |
|
|
224
231
|
|------|-------------|------------|
|
|
@@ -243,7 +250,7 @@ This turns "set EQ band 3 to -4 dB" into "cut 400 Hz by 4 dB, then read the spec
|
|
|
243
250
|
| `stop_scrub` | Stop preview | `track_index`, `clip_index` |
|
|
244
251
|
| `get_display_values` | Human-readable parameter values ("440 Hz", "-6 dB") | `track_index`, `device_index` |
|
|
245
252
|
|
|
246
|
-
### Automation (8) — Clip automation CRUD + intelligent curve generation
|
|
253
|
+
### Automation (showing 8 of 9) — Clip automation CRUD + intelligent curve generation
|
|
247
254
|
|
|
248
255
|
| Tool | What it does | Key params |
|
|
249
256
|
|------|-------------|------------|
|