@kernel.chat/kbot 3.58.0 → 3.59.0
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/README.md +4 -4
- package/dist/agent.d.ts +2 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +14 -8
- package/dist/agent.js.map +1 -1
- package/dist/agents/replit.js +1 -1
- package/dist/bootstrap.js +1 -1
- package/dist/integrations/ableton-live.d.ts +52 -0
- package/dist/integrations/ableton-live.d.ts.map +1 -0
- package/dist/integrations/ableton-live.js +239 -0
- package/dist/integrations/ableton-live.js.map +1 -0
- package/dist/integrations/ableton-osc-installer.d.ts +13 -0
- package/dist/integrations/ableton-osc-installer.d.ts.map +1 -0
- package/dist/integrations/ableton-osc-installer.js +190 -0
- package/dist/integrations/ableton-osc-installer.js.map +1 -0
- package/dist/learning.d.ts.map +1 -1
- package/dist/learning.js +20 -0
- package/dist/learning.js.map +1 -1
- package/dist/memory.d.ts +8 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +42 -23
- package/dist/memory.js.map +1 -1
- package/dist/memory.test.js +83 -2
- package/dist/memory.test.js.map +1 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +8 -0
- package/dist/serve.js.map +1 -1
- package/dist/tools/computer.d.ts.map +1 -1
- package/dist/tools/computer.js +815 -53
- package/dist/tools/computer.js.map +1 -1
- package/dist/tools/dj-set-builder.d.ts +2 -0
- package/dist/tools/dj-set-builder.d.ts.map +1 -0
- package/dist/tools/dj-set-builder.js +432 -0
- package/dist/tools/dj-set-builder.js.map +1 -0
- package/dist/tools/fetch.d.ts.map +1 -1
- package/dist/tools/fetch.js +36 -6
- package/dist/tools/fetch.js.map +1 -1
- package/dist/tools/files.d.ts.map +1 -1
- package/dist/tools/files.js +40 -23
- package/dist/tools/files.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/serum2-preset.d.ts +11 -0
- package/dist/tools/serum2-preset.d.ts.map +1 -0
- package/dist/tools/serum2-preset.js +143 -0
- package/dist/tools/serum2-preset.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ableton-live.ts — kbot ↔ Ableton Live via AbletonOSC (UDP)
|
|
3
|
+
*
|
|
4
|
+
* Provides full Ableton control:
|
|
5
|
+
* - Transport (play, stop, tempo)
|
|
6
|
+
* - Tracks (create, name, volume, pan, mute, solo)
|
|
7
|
+
* - Devices (load any instrument/effect by name)
|
|
8
|
+
* - Clips (create, add notes, fire, stop)
|
|
9
|
+
* - Mixing (volume, sends)
|
|
10
|
+
* - Exec (arbitrary Python inside Ableton's runtime)
|
|
11
|
+
*
|
|
12
|
+
* Requires AbletonOSC installed: kbot ableton setup
|
|
13
|
+
*/
|
|
14
|
+
import * as dgram from 'node:dgram';
|
|
15
|
+
import { Buffer } from 'node:buffer';
|
|
16
|
+
const OSC_SEND_PORT = 11000;
|
|
17
|
+
const OSC_RECV_PORT = 11001;
|
|
18
|
+
const OSC_HOST = '127.0.0.1';
|
|
19
|
+
// ── OSC Protocol ────────────────────────────────────────────────────────
|
|
20
|
+
function oscEncode(addr, ...args) {
|
|
21
|
+
let addrBuf = Buffer.from(addr + '\0');
|
|
22
|
+
while (addrBuf.length % 4)
|
|
23
|
+
addrBuf = Buffer.concat([addrBuf, Buffer.alloc(1)]);
|
|
24
|
+
let typetag = ',';
|
|
25
|
+
const argBufs = [];
|
|
26
|
+
for (const a of args) {
|
|
27
|
+
if (typeof a === 'number' && Number.isInteger(a)) {
|
|
28
|
+
typetag += 'i';
|
|
29
|
+
const b = Buffer.alloc(4);
|
|
30
|
+
b.writeInt32BE(a);
|
|
31
|
+
argBufs.push(b);
|
|
32
|
+
}
|
|
33
|
+
else if (typeof a === 'number') {
|
|
34
|
+
typetag += 'f';
|
|
35
|
+
const b = Buffer.alloc(4);
|
|
36
|
+
b.writeFloatBE(a);
|
|
37
|
+
argBufs.push(b);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
typetag += 's';
|
|
41
|
+
let sb = Buffer.from(a + '\0');
|
|
42
|
+
while (sb.length % 4)
|
|
43
|
+
sb = Buffer.concat([sb, Buffer.alloc(1)]);
|
|
44
|
+
argBufs.push(sb);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
let ttBuf = Buffer.from(typetag + '\0');
|
|
48
|
+
while (ttBuf.length % 4)
|
|
49
|
+
ttBuf = Buffer.concat([ttBuf, Buffer.alloc(1)]);
|
|
50
|
+
return Buffer.concat([addrBuf, ttBuf, ...argBufs]);
|
|
51
|
+
}
|
|
52
|
+
function oscParse(data) {
|
|
53
|
+
const end = data.indexOf(0);
|
|
54
|
+
const address = data.subarray(0, end).toString();
|
|
55
|
+
let pos = end + 1;
|
|
56
|
+
while (pos % 4)
|
|
57
|
+
pos++;
|
|
58
|
+
const args = [];
|
|
59
|
+
if (pos < data.length && data[pos] === 0x2c) { // ','
|
|
60
|
+
const tagEnd = data.indexOf(0, pos);
|
|
61
|
+
const tags = data.subarray(pos + 1, tagEnd).toString();
|
|
62
|
+
pos = tagEnd + 1;
|
|
63
|
+
while (pos % 4)
|
|
64
|
+
pos++;
|
|
65
|
+
for (const t of tags) {
|
|
66
|
+
if (t === 'i') {
|
|
67
|
+
args.push(data.readInt32BE(pos));
|
|
68
|
+
pos += 4;
|
|
69
|
+
}
|
|
70
|
+
else if (t === 'f') {
|
|
71
|
+
args.push(Math.round(data.readFloatBE(pos) * 10000) / 10000);
|
|
72
|
+
pos += 4;
|
|
73
|
+
}
|
|
74
|
+
else if (t === 's') {
|
|
75
|
+
const sEnd = data.indexOf(0, pos);
|
|
76
|
+
args.push(data.subarray(pos, sEnd).toString());
|
|
77
|
+
pos = sEnd + 1;
|
|
78
|
+
while (pos % 4)
|
|
79
|
+
pos++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { address, args };
|
|
84
|
+
}
|
|
85
|
+
// ── AbletonLive Client ──────────────────────────────────────────────────
|
|
86
|
+
export class AbletonLive {
|
|
87
|
+
static instance = null;
|
|
88
|
+
socket = null;
|
|
89
|
+
connected = false;
|
|
90
|
+
static getInstance() {
|
|
91
|
+
if (!AbletonLive.instance) {
|
|
92
|
+
AbletonLive.instance = new AbletonLive();
|
|
93
|
+
}
|
|
94
|
+
return AbletonLive.instance;
|
|
95
|
+
}
|
|
96
|
+
async connect() {
|
|
97
|
+
if (this.connected && this.socket)
|
|
98
|
+
return true;
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
this.socket = dgram.createSocket('udp4');
|
|
101
|
+
this.socket.bind(OSC_RECV_PORT, OSC_HOST, () => {
|
|
102
|
+
// Test connection with tempo query
|
|
103
|
+
this.query('/live/song/get/tempo')
|
|
104
|
+
.then(r => {
|
|
105
|
+
this.connected = r.args.length > 0;
|
|
106
|
+
resolve(this.connected);
|
|
107
|
+
})
|
|
108
|
+
.catch(() => {
|
|
109
|
+
this.connected = false;
|
|
110
|
+
resolve(false);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
this.socket.on('error', () => {
|
|
114
|
+
this.connected = false;
|
|
115
|
+
resolve(false);
|
|
116
|
+
});
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
if (!this.connected)
|
|
119
|
+
resolve(false);
|
|
120
|
+
}, 5000);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
disconnect() {
|
|
124
|
+
this.socket?.close();
|
|
125
|
+
this.socket = null;
|
|
126
|
+
this.connected = false;
|
|
127
|
+
}
|
|
128
|
+
get isConnected() {
|
|
129
|
+
return this.connected;
|
|
130
|
+
}
|
|
131
|
+
/** Send OSC message, no response expected. */
|
|
132
|
+
send(addr, ...args) {
|
|
133
|
+
if (!this.socket)
|
|
134
|
+
return;
|
|
135
|
+
this.socket.send(oscEncode(addr, ...args), OSC_SEND_PORT, OSC_HOST);
|
|
136
|
+
}
|
|
137
|
+
/** Send OSC message and wait for response. */
|
|
138
|
+
async query(addr, ...args) {
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
if (!this.socket)
|
|
141
|
+
return reject(new Error('Not connected'));
|
|
142
|
+
// Flush pending messages
|
|
143
|
+
this.socket.removeAllListeners('message');
|
|
144
|
+
const timer = setTimeout(() => {
|
|
145
|
+
reject(new Error('Timeout'));
|
|
146
|
+
}, 10000);
|
|
147
|
+
this.socket.once('message', (msg) => {
|
|
148
|
+
clearTimeout(timer);
|
|
149
|
+
resolve(oscParse(msg));
|
|
150
|
+
});
|
|
151
|
+
this.socket.send(oscEncode(addr, ...args), OSC_SEND_PORT, OSC_HOST);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// ── Convenience Methods ─────────────────────────────────────────────
|
|
155
|
+
async getTempo() {
|
|
156
|
+
const r = await this.query('/live/song/get/tempo');
|
|
157
|
+
return r.args[0];
|
|
158
|
+
}
|
|
159
|
+
setTempo(bpm) {
|
|
160
|
+
this.send('/live/song/set/tempo', bpm);
|
|
161
|
+
}
|
|
162
|
+
play() { this.send('/live/song/start_playing'); }
|
|
163
|
+
stop() { this.send('/live/song/stop_playing'); }
|
|
164
|
+
async getTrackCount() {
|
|
165
|
+
const r = await this.query('/live/song/get/num_tracks');
|
|
166
|
+
return r.args[0];
|
|
167
|
+
}
|
|
168
|
+
async createMidiTrack(name) {
|
|
169
|
+
this.send('/live/song/create_midi_track', -1);
|
|
170
|
+
await new Promise(r => setTimeout(r, 400));
|
|
171
|
+
const count = await this.getTrackCount();
|
|
172
|
+
const trackIdx = count - 2;
|
|
173
|
+
this.send('/live/track/set/name', trackIdx, name);
|
|
174
|
+
return trackIdx;
|
|
175
|
+
}
|
|
176
|
+
async loadDevice(track, searchTerm) {
|
|
177
|
+
const r = await this.query('/live/track/load/device', track, searchTerm);
|
|
178
|
+
return r.args[1] || 'unknown';
|
|
179
|
+
}
|
|
180
|
+
setVolume(track, volume) {
|
|
181
|
+
this.send('/live/track/set/volume', track, volume);
|
|
182
|
+
}
|
|
183
|
+
async createClip(track, slot, length, name) {
|
|
184
|
+
this.send('/live/clip_slot/create_clip', track, slot, length);
|
|
185
|
+
await new Promise(r => setTimeout(r, 300));
|
|
186
|
+
this.send('/live/clip/set/name', track, slot, name);
|
|
187
|
+
}
|
|
188
|
+
addNote(track, slot, pitch, start, duration, velocity) {
|
|
189
|
+
this.send('/live/clip/add/notes', track, slot, pitch, start, duration, velocity, 0);
|
|
190
|
+
}
|
|
191
|
+
fireClip(track, slot) {
|
|
192
|
+
this.send('/live/clip_slot/fire', track, slot);
|
|
193
|
+
}
|
|
194
|
+
/** Execute arbitrary Python in Ableton's runtime. */
|
|
195
|
+
async exec(code) {
|
|
196
|
+
const r = await this.query('/live/exec', code);
|
|
197
|
+
return r.args[0] || '';
|
|
198
|
+
}
|
|
199
|
+
/** Delete all tracks for a clean slate. */
|
|
200
|
+
async clearAllTracks() {
|
|
201
|
+
const count = await this.getTrackCount();
|
|
202
|
+
for (let t = count - 2; t >= 0; t--) {
|
|
203
|
+
this.send('/live/song/delete_track', t);
|
|
204
|
+
await new Promise(r => setTimeout(r, 120));
|
|
205
|
+
}
|
|
206
|
+
await new Promise(r => setTimeout(r, 500));
|
|
207
|
+
}
|
|
208
|
+
/** Get all track names and devices. */
|
|
209
|
+
async getSessionInfo() {
|
|
210
|
+
const count = await this.getTrackCount();
|
|
211
|
+
const tracks = [];
|
|
212
|
+
for (let t = 0; t < count - 1; t++) {
|
|
213
|
+
const nameR = await this.query('/live/track/get/name', t);
|
|
214
|
+
const devR = await this.query('/live/track/get/devices/name', t);
|
|
215
|
+
tracks.push({
|
|
216
|
+
index: t,
|
|
217
|
+
name: nameR.args[1] || `Track ${t}`,
|
|
218
|
+
devices: devR.args.slice(1),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return tracks;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// ── Convenience export ──────────────────────────────────────────────────
|
|
225
|
+
export async function ensureAbleton() {
|
|
226
|
+
const live = AbletonLive.getInstance();
|
|
227
|
+
if (live.isConnected)
|
|
228
|
+
return live;
|
|
229
|
+
const ok = await live.connect();
|
|
230
|
+
if (!ok) {
|
|
231
|
+
throw new Error('Cannot connect to Ableton Live via AbletonOSC.\n\n' +
|
|
232
|
+
'Make sure:\n' +
|
|
233
|
+
'1. Ableton Live is running\n' +
|
|
234
|
+
'2. AbletonOSC is enabled in Preferences > Link, Tempo & MIDI > Control Surface\n' +
|
|
235
|
+
'3. Run `kbot ableton setup` if AbletonOSC is not installed\n');
|
|
236
|
+
}
|
|
237
|
+
return live;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=ableton-live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ableton-live.js","sourceRoot":"","sources":["../../src/integrations/ableton-live.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ableton-osc-installer.ts — Install and patch AbletonOSC for kbot control
|
|
3
|
+
*
|
|
4
|
+
* Installs AbletonOSC remote script into Ableton's User Library,
|
|
5
|
+
* patches it with kbot extensions (device loading, Python exec),
|
|
6
|
+
* and provides setup instructions.
|
|
7
|
+
*
|
|
8
|
+
* Usage: kbot ableton setup
|
|
9
|
+
*/
|
|
10
|
+
export declare function installAbletonOSC(): Promise<string>;
|
|
11
|
+
export declare function isAbletonOSCInstalled(): boolean;
|
|
12
|
+
export declare function isKbotPatched(): boolean;
|
|
13
|
+
//# sourceMappingURL=ableton-osc-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ableton-osc-installer.d.ts","sourceRoot":"","sources":["../../src/integrations/ableton-osc-installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6GH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CA+EzD;AAED,wBAAgB,qBAAqB,IAAI,OAAO,CAG/C;AAED,wBAAgB,aAAa,IAAI,OAAO,CAKvC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ableton-osc-installer.ts — Install and patch AbletonOSC for kbot control
|
|
3
|
+
*
|
|
4
|
+
* Installs AbletonOSC remote script into Ableton's User Library,
|
|
5
|
+
* patches it with kbot extensions (device loading, Python exec),
|
|
6
|
+
* and provides setup instructions.
|
|
7
|
+
*
|
|
8
|
+
* Usage: kbot ableton setup
|
|
9
|
+
*/
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import * as os from 'node:os';
|
|
14
|
+
const REPO_URL = 'https://github.com/ideoforms/AbletonOSC.git';
|
|
15
|
+
function getAbletonUserLibrary() {
|
|
16
|
+
const home = os.homedir();
|
|
17
|
+
return path.join(home, 'Music', 'Ableton', 'User Library', 'Remote Scripts', 'AbletonOSC');
|
|
18
|
+
}
|
|
19
|
+
function getAbletonPrefsDir() {
|
|
20
|
+
const home = os.homedir();
|
|
21
|
+
const prefsBase = path.join(home, 'Library', 'Preferences', 'Ableton');
|
|
22
|
+
if (!fs.existsSync(prefsBase))
|
|
23
|
+
return [];
|
|
24
|
+
return fs.readdirSync(prefsBase)
|
|
25
|
+
.filter(d => d.startsWith('Live'))
|
|
26
|
+
.map(d => path.join(prefsBase, d))
|
|
27
|
+
.sort()
|
|
28
|
+
.reverse();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The kbot patch for AbletonOSC's song.py — adds device loading via browser API.
|
|
32
|
+
*/
|
|
33
|
+
const DEVICE_LOADER_PATCH = `
|
|
34
|
+
#--------------------------------------------------------------------------------
|
|
35
|
+
# kbot: Load device onto track by browser search
|
|
36
|
+
# /live/track/load/device <track_index> <search_term>
|
|
37
|
+
#--------------------------------------------------------------------------------
|
|
38
|
+
def track_load_device(params):
|
|
39
|
+
try:
|
|
40
|
+
track_index = int(params[0])
|
|
41
|
+
search_term = str(params[1]).lower()
|
|
42
|
+
track = self.song.tracks[track_index]
|
|
43
|
+
self.song.view.selected_track = track
|
|
44
|
+
browser = self.manager.application.browser
|
|
45
|
+
|
|
46
|
+
found = None
|
|
47
|
+
def search_recursive(item, term, depth=0):
|
|
48
|
+
nonlocal found
|
|
49
|
+
if found or depth > 5: return
|
|
50
|
+
try:
|
|
51
|
+
for child in item.children:
|
|
52
|
+
if term in child.name.lower():
|
|
53
|
+
if child.is_loadable:
|
|
54
|
+
src = str(child.source) if hasattr(child, 'source') else ''
|
|
55
|
+
if 'UAD' not in src:
|
|
56
|
+
found = child
|
|
57
|
+
return
|
|
58
|
+
search_recursive(child, term, depth + 1)
|
|
59
|
+
else:
|
|
60
|
+
search_recursive(child, term, depth + 1)
|
|
61
|
+
except: pass
|
|
62
|
+
|
|
63
|
+
for root in [browser.plugins, browser.instruments, browser.audio_effects,
|
|
64
|
+
browser.midi_effects, browser.max_for_live, browser.drums]:
|
|
65
|
+
try:
|
|
66
|
+
search_recursive(root, search_term)
|
|
67
|
+
if found: break
|
|
68
|
+
except: continue
|
|
69
|
+
|
|
70
|
+
if found:
|
|
71
|
+
browser.load_item(found)
|
|
72
|
+
self.logger.info("kbot: Loaded device: %s" % found.name)
|
|
73
|
+
return (1, found.name)
|
|
74
|
+
else:
|
|
75
|
+
return (0, "not found")
|
|
76
|
+
except Exception as e:
|
|
77
|
+
return (0, str(e))
|
|
78
|
+
self.osc_server.add_handler("/live/track/load/device", track_load_device)
|
|
79
|
+
`;
|
|
80
|
+
/**
|
|
81
|
+
* The kbot patch for AbletonOSC's device.py — adds Python exec for deep control.
|
|
82
|
+
*/
|
|
83
|
+
const EXEC_PATCH = `
|
|
84
|
+
#--------------------------------------------------------------------------------
|
|
85
|
+
# kbot: Execute Python in Ableton's runtime
|
|
86
|
+
# /live/exec <code_string>
|
|
87
|
+
#--------------------------------------------------------------------------------
|
|
88
|
+
def live_exec(params):
|
|
89
|
+
code = str(params[0])
|
|
90
|
+
try:
|
|
91
|
+
result = eval(code, {
|
|
92
|
+
'song': self.song,
|
|
93
|
+
'app': self.manager.application,
|
|
94
|
+
'Live': __import__('Live'),
|
|
95
|
+
'tracks': self.song.tracks,
|
|
96
|
+
})
|
|
97
|
+
return (str(result),)
|
|
98
|
+
except SyntaxError:
|
|
99
|
+
local_vars = {
|
|
100
|
+
'song': self.song,
|
|
101
|
+
'app': self.manager.application,
|
|
102
|
+
'Live': __import__('Live'),
|
|
103
|
+
'tracks': self.song.tracks,
|
|
104
|
+
'_result': None,
|
|
105
|
+
}
|
|
106
|
+
exec(code, local_vars)
|
|
107
|
+
return (str(local_vars.get('_result', 'ok')),)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
return ("ERROR: " + str(e),)
|
|
110
|
+
self.osc_server.add_handler("/live/exec", live_exec)
|
|
111
|
+
`;
|
|
112
|
+
export async function installAbletonOSC() {
|
|
113
|
+
const destDir = getAbletonUserLibrary();
|
|
114
|
+
const tmpDir = path.join(os.tmpdir(), 'kbot-abletonosc');
|
|
115
|
+
const lines = [];
|
|
116
|
+
const log = (msg) => { lines.push(msg); console.log(msg); };
|
|
117
|
+
log('Installing AbletonOSC for kbot...');
|
|
118
|
+
// Clone or update
|
|
119
|
+
if (fs.existsSync(tmpDir)) {
|
|
120
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
execSync(`git clone --depth 1 ${REPO_URL} "${tmpDir}"`, { stdio: 'pipe' });
|
|
124
|
+
log(' Cloned AbletonOSC');
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
log(' ERROR: Could not clone AbletonOSC. Check internet connection.');
|
|
128
|
+
return lines.join('\n');
|
|
129
|
+
}
|
|
130
|
+
// Apply kbot patches
|
|
131
|
+
const songPy = path.join(tmpDir, 'abletonosc', 'song.py');
|
|
132
|
+
const devicePy = path.join(tmpDir, 'abletonosc', 'device.py');
|
|
133
|
+
if (fs.existsSync(songPy)) {
|
|
134
|
+
let content = fs.readFileSync(songPy, 'utf8');
|
|
135
|
+
// Insert device loader before Scene properties section
|
|
136
|
+
content = content.replace(' # Callbacks for Song: Scene properties', DEVICE_LOADER_PATCH + '\n # Callbacks for Song: Scene properties');
|
|
137
|
+
fs.writeFileSync(songPy, content);
|
|
138
|
+
log(' Patched song.py with device loader');
|
|
139
|
+
}
|
|
140
|
+
if (fs.existsSync(devicePy)) {
|
|
141
|
+
let content = fs.readFileSync(devicePy, 'utf8');
|
|
142
|
+
// Append exec handler at the end of init_api
|
|
143
|
+
const lastHandler = content.lastIndexOf('self.osc_server.add_handler');
|
|
144
|
+
if (lastHandler !== -1) {
|
|
145
|
+
const insertPos = content.indexOf('\n', lastHandler) + 1;
|
|
146
|
+
content = content.slice(0, insertPos) + EXEC_PATCH + content.slice(insertPos);
|
|
147
|
+
}
|
|
148
|
+
fs.writeFileSync(devicePy, content);
|
|
149
|
+
log(' Patched device.py with exec handler');
|
|
150
|
+
}
|
|
151
|
+
// Copy to Ableton User Library
|
|
152
|
+
const parentDir = path.dirname(destDir);
|
|
153
|
+
if (!fs.existsSync(parentDir)) {
|
|
154
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
155
|
+
}
|
|
156
|
+
if (fs.existsSync(destDir)) {
|
|
157
|
+
fs.rmSync(destDir, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
fs.cpSync(tmpDir, destDir, { recursive: true });
|
|
160
|
+
log(` Installed to ${destDir}`);
|
|
161
|
+
// Clean up
|
|
162
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
163
|
+
log('');
|
|
164
|
+
log('AbletonOSC installed with kbot extensions.');
|
|
165
|
+
log('');
|
|
166
|
+
log('To activate:');
|
|
167
|
+
log(' 1. Open Ableton Live');
|
|
168
|
+
log(' 2. Preferences (Cmd+,) > Link, Tempo & MIDI');
|
|
169
|
+
log(' 3. Set a Control Surface to "AbletonOSC"');
|
|
170
|
+
log(' 4. Close Preferences');
|
|
171
|
+
log('');
|
|
172
|
+
log('kbot commands available after activation:');
|
|
173
|
+
log(' kbot ableton status — Check connection');
|
|
174
|
+
log(' kbot ableton session — Build a session from a prompt');
|
|
175
|
+
log(' kbot ableton load — Load any device onto a track');
|
|
176
|
+
log(' kbot ableton preset — Create Serum 2 presets');
|
|
177
|
+
return lines.join('\n');
|
|
178
|
+
}
|
|
179
|
+
export function isAbletonOSCInstalled() {
|
|
180
|
+
const destDir = getAbletonUserLibrary();
|
|
181
|
+
return fs.existsSync(path.join(destDir, '__init__.py'));
|
|
182
|
+
}
|
|
183
|
+
export function isKbotPatched() {
|
|
184
|
+
const songPy = path.join(getAbletonUserLibrary(), 'abletonosc', 'song.py');
|
|
185
|
+
if (!fs.existsSync(songPy))
|
|
186
|
+
return false;
|
|
187
|
+
const content = fs.readFileSync(songPy, 'utf8');
|
|
188
|
+
return content.includes('track_load_device');
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=ableton-osc-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ableton-osc-installer.js","sourceRoot":"","sources":["../../src/integrations/ableton-osc-installer.ts"],"names":[],"mappings":"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"}
|
package/dist/learning.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learning.d.ts","sourceRoot":"","sources":["../src/learning.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learning.d.ts","sourceRoot":"","sources":["../src/learning.ts"],"names":[],"mappings":"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"}
|
package/dist/learning.js
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
// 3. USER PROFILE — Learn user preferences, style, and common workflows
|
|
9
9
|
//
|
|
10
10
|
// Everything persists to ~/.kbot/memory/ as JSON files.
|
|
11
|
+
//
|
|
12
|
+
// CONCURRENCY NOTE: Module-level state (patterns, solutions, profile, etc.) is
|
|
13
|
+
// intentionally shared across concurrent requests in `kbot serve` mode — learning
|
|
14
|
+
// data is cumulative and global. All mutation functions are synchronous, so they
|
|
15
|
+
// cannot interleave in Node.js's single-threaded event loop. The debounced saveJSON
|
|
16
|
+
// writer coalesces concurrent writes. selfTrain() uses a guard to prevent overlapping runs.
|
|
11
17
|
import { homedir } from 'node:os';
|
|
12
18
|
import { join } from 'node:path';
|
|
13
19
|
import { existsSync, readFileSync, writeFileSync, writeFile, mkdirSync } from 'node:fs';
|
|
@@ -704,8 +710,22 @@ let trainingLog = loadJSON(TRAINING_FILE, {
|
|
|
704
710
|
insightsSynthesized: 0,
|
|
705
711
|
patternsOptimized: 0,
|
|
706
712
|
});
|
|
713
|
+
/** Guard to prevent overlapping selfTrain runs in serve mode */
|
|
714
|
+
let selfTrainRunning = false;
|
|
707
715
|
/** Run self-training: prune stale knowledge, optimize patterns, synthesize insights */
|
|
708
716
|
export function selfTrain() {
|
|
717
|
+
if (selfTrainRunning) {
|
|
718
|
+
return { pruned: 0, optimized: 0, synthesized: 0, summary: 'Self-training already in progress — skipped.' };
|
|
719
|
+
}
|
|
720
|
+
selfTrainRunning = true;
|
|
721
|
+
try {
|
|
722
|
+
return selfTrainInner();
|
|
723
|
+
}
|
|
724
|
+
finally {
|
|
725
|
+
selfTrainRunning = false;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
function selfTrainInner() {
|
|
709
729
|
let pruned = 0;
|
|
710
730
|
let optimized = 0;
|
|
711
731
|
let synthesized = 0;
|