open-agents-ai 0.93.1 → 0.95.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/dist/index.js +327 -12
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -32523,13 +32523,66 @@ var init_voice = __esm({
|
|
|
32523
32523
|
id: "glados",
|
|
32524
32524
|
label: "GLaDOS",
|
|
32525
32525
|
onnxUrl: "https://raw.githubusercontent.com/robit-man/EGG/main/voice/glados_piper_medium.onnx",
|
|
32526
|
-
configUrl: "https://raw.githubusercontent.com/robit-man/EGG/main/voice/glados_piper_medium.onnx.json"
|
|
32526
|
+
configUrl: "https://raw.githubusercontent.com/robit-man/EGG/main/voice/glados_piper_medium.onnx.json",
|
|
32527
|
+
backend: "onnx"
|
|
32527
32528
|
},
|
|
32528
32529
|
overwatch: {
|
|
32529
32530
|
id: "overwatch",
|
|
32530
32531
|
label: "Overwatch",
|
|
32531
32532
|
onnxUrl: "https://raw.githubusercontent.com/robit-man/combine_overwatch_onnx/main/overwatch.onnx",
|
|
32532
|
-
configUrl: "https://raw.githubusercontent.com/robit-man/combine_overwatch_onnx/main/overwatch.onnx.json"
|
|
32533
|
+
configUrl: "https://raw.githubusercontent.com/robit-man/combine_overwatch_onnx/main/overwatch.onnx.json",
|
|
32534
|
+
backend: "onnx"
|
|
32535
|
+
},
|
|
32536
|
+
// MLX Audio models — macOS Apple Silicon only
|
|
32537
|
+
kokoro: {
|
|
32538
|
+
id: "kokoro",
|
|
32539
|
+
label: "Kokoro (MLX)",
|
|
32540
|
+
onnxUrl: "",
|
|
32541
|
+
configUrl: "",
|
|
32542
|
+
backend: "mlx",
|
|
32543
|
+
mlxModelId: "mlx-community/Kokoro-82M-bf16",
|
|
32544
|
+
mlxVoice: "af_heart",
|
|
32545
|
+
mlxLangCode: "a"
|
|
32546
|
+
},
|
|
32547
|
+
"kokoro:af_heart": {
|
|
32548
|
+
id: "kokoro:af_heart",
|
|
32549
|
+
label: "Kokoro Heart (MLX)",
|
|
32550
|
+
onnxUrl: "",
|
|
32551
|
+
configUrl: "",
|
|
32552
|
+
backend: "mlx",
|
|
32553
|
+
mlxModelId: "mlx-community/Kokoro-82M-bf16",
|
|
32554
|
+
mlxVoice: "af_heart",
|
|
32555
|
+
mlxLangCode: "a"
|
|
32556
|
+
},
|
|
32557
|
+
"kokoro:af_bella": {
|
|
32558
|
+
id: "kokoro:af_bella",
|
|
32559
|
+
label: "Kokoro Bella (MLX)",
|
|
32560
|
+
onnxUrl: "",
|
|
32561
|
+
configUrl: "",
|
|
32562
|
+
backend: "mlx",
|
|
32563
|
+
mlxModelId: "mlx-community/Kokoro-82M-bf16",
|
|
32564
|
+
mlxVoice: "af_bella",
|
|
32565
|
+
mlxLangCode: "a"
|
|
32566
|
+
},
|
|
32567
|
+
"kokoro:am_adam": {
|
|
32568
|
+
id: "kokoro:am_adam",
|
|
32569
|
+
label: "Kokoro Adam (MLX)",
|
|
32570
|
+
onnxUrl: "",
|
|
32571
|
+
configUrl: "",
|
|
32572
|
+
backend: "mlx",
|
|
32573
|
+
mlxModelId: "mlx-community/Kokoro-82M-bf16",
|
|
32574
|
+
mlxVoice: "am_adam",
|
|
32575
|
+
mlxLangCode: "a"
|
|
32576
|
+
},
|
|
32577
|
+
"kokoro:bf_emma": {
|
|
32578
|
+
id: "kokoro:bf_emma",
|
|
32579
|
+
label: "Kokoro Emma (MLX)",
|
|
32580
|
+
onnxUrl: "",
|
|
32581
|
+
configUrl: "",
|
|
32582
|
+
backend: "mlx",
|
|
32583
|
+
mlxModelId: "mlx-community/Kokoro-82M-bf16",
|
|
32584
|
+
mlxVoice: "bf_emma",
|
|
32585
|
+
mlxLangCode: "b"
|
|
32533
32586
|
}
|
|
32534
32587
|
};
|
|
32535
32588
|
VoiceEngine = class {
|
|
@@ -32551,6 +32604,12 @@ var init_voice = __esm({
|
|
|
32551
32604
|
speakQueue = [];
|
|
32552
32605
|
speaking = false;
|
|
32553
32606
|
phonemizeFn = null;
|
|
32607
|
+
/** True when current model uses MLX Audio backend */
|
|
32608
|
+
mlxActive = false;
|
|
32609
|
+
/** Cached: is mlx-audio pip package installed? */
|
|
32610
|
+
mlxInstalled = null;
|
|
32611
|
+
/** Path to python3 binary (resolved once) */
|
|
32612
|
+
python3Path = null;
|
|
32554
32613
|
// -------------------------------------------------------------------------
|
|
32555
32614
|
// Public API
|
|
32556
32615
|
// -------------------------------------------------------------------------
|
|
@@ -32560,13 +32619,21 @@ var init_voice = __esm({
|
|
|
32560
32619
|
this.killPlayback();
|
|
32561
32620
|
return "Voice feedback disabled.";
|
|
32562
32621
|
}
|
|
32622
|
+
const model = VOICE_MODELS[this.modelId];
|
|
32623
|
+
const isMlx = model?.backend === "mlx";
|
|
32563
32624
|
try {
|
|
32564
|
-
|
|
32565
|
-
|
|
32566
|
-
|
|
32625
|
+
if (isMlx) {
|
|
32626
|
+
await this.ensureMlxAudio();
|
|
32627
|
+
this.mlxActive = true;
|
|
32628
|
+
} else {
|
|
32629
|
+
await this.ensureRuntime();
|
|
32630
|
+
await this.ensureModel(this.modelId);
|
|
32631
|
+
await this.loadSession();
|
|
32632
|
+
this.mlxActive = false;
|
|
32633
|
+
}
|
|
32567
32634
|
this.enabled = true;
|
|
32568
32635
|
this.ready = true;
|
|
32569
|
-
return `Voice feedback enabled (${
|
|
32636
|
+
return `Voice feedback enabled (${model?.label ?? this.modelId}).`;
|
|
32570
32637
|
} catch (err) {
|
|
32571
32638
|
return `Failed to enable voice: ${err instanceof Error ? err.message : String(err)}`;
|
|
32572
32639
|
}
|
|
@@ -32574,24 +32641,36 @@ var init_voice = __esm({
|
|
|
32574
32641
|
async setModel(id) {
|
|
32575
32642
|
const key = id.toLowerCase();
|
|
32576
32643
|
if (!VOICE_MODELS[key]) {
|
|
32577
|
-
|
|
32578
|
-
|
|
32644
|
+
const onnxModels = Object.keys(VOICE_MODELS).filter((k) => VOICE_MODELS[k].backend !== "mlx");
|
|
32645
|
+
const mlxModels = Object.keys(VOICE_MODELS).filter((k) => VOICE_MODELS[k].backend === "mlx");
|
|
32646
|
+
return `Unknown voice model: "${id}". Available:
|
|
32647
|
+
ONNX: ${onnxModels.join(", ")}
|
|
32648
|
+
MLX (macOS): ${mlxModels.join(", ")}`;
|
|
32649
|
+
}
|
|
32650
|
+
const model = VOICE_MODELS[key];
|
|
32651
|
+
const isMlx = model.backend === "mlx";
|
|
32579
32652
|
this.modelId = key;
|
|
32580
32653
|
this.session = null;
|
|
32581
32654
|
this.config = null;
|
|
32582
32655
|
this.ready = false;
|
|
32583
32656
|
if (this.enabled) {
|
|
32584
32657
|
try {
|
|
32585
|
-
|
|
32586
|
-
|
|
32658
|
+
if (isMlx) {
|
|
32659
|
+
await this.ensureMlxAudio();
|
|
32660
|
+
this.mlxActive = true;
|
|
32661
|
+
} else {
|
|
32662
|
+
await this.ensureModel(key);
|
|
32663
|
+
await this.loadSession();
|
|
32664
|
+
this.mlxActive = false;
|
|
32665
|
+
}
|
|
32587
32666
|
this.ready = true;
|
|
32588
|
-
return `Switched to ${
|
|
32667
|
+
return `Switched to ${model.label} voice.`;
|
|
32589
32668
|
} catch (err) {
|
|
32590
32669
|
this.enabled = false;
|
|
32591
32670
|
return `Failed to load ${key}: ${err instanceof Error ? err.message : String(err)}`;
|
|
32592
32671
|
}
|
|
32593
32672
|
}
|
|
32594
|
-
return `Voice model set to ${
|
|
32673
|
+
return `Voice model set to ${model.label}. Enable with /voice.`;
|
|
32595
32674
|
}
|
|
32596
32675
|
/**
|
|
32597
32676
|
* Speak text asynchronously (non-blocking) at full volume.
|
|
@@ -32636,6 +32715,9 @@ var init_voice = __esm({
|
|
|
32636
32715
|
* Used for sending TTS audio to Telegram and WebSocket clients.
|
|
32637
32716
|
*/
|
|
32638
32717
|
async synthesizeToBuffer(text) {
|
|
32718
|
+
if (this.mlxActive) {
|
|
32719
|
+
return this.synthesizeMlxToBuffer(text);
|
|
32720
|
+
}
|
|
32639
32721
|
if (!this.session || !this.config || !this.ort)
|
|
32640
32722
|
return null;
|
|
32641
32723
|
const cleaned = text.replace(/\*/g, "");
|
|
@@ -32668,6 +32750,14 @@ var init_voice = __esm({
|
|
|
32668
32750
|
* Used for streaming to WebSocket clients.
|
|
32669
32751
|
*/
|
|
32670
32752
|
async synthesizeToPCM(text) {
|
|
32753
|
+
if (this.mlxActive) {
|
|
32754
|
+
const wav = await this.synthesizeMlxToBuffer(text);
|
|
32755
|
+
if (!wav || wav.length <= 44)
|
|
32756
|
+
return null;
|
|
32757
|
+
const sampleRate = wav.readUInt32LE(24);
|
|
32758
|
+
const pcm = Buffer.from(wav.buffer, wav.byteOffset + 44, wav.length - 44);
|
|
32759
|
+
return { pcm, sampleRate };
|
|
32760
|
+
}
|
|
32671
32761
|
if (!this.session || !this.config || !this.ort)
|
|
32672
32762
|
return null;
|
|
32673
32763
|
const cleaned = text.replace(/\*/g, "");
|
|
@@ -32705,6 +32795,8 @@ var init_voice = __esm({
|
|
|
32705
32795
|
}
|
|
32706
32796
|
/** Get the current model's sample rate */
|
|
32707
32797
|
get sampleRate() {
|
|
32798
|
+
if (this.mlxActive)
|
|
32799
|
+
return 24e3;
|
|
32708
32800
|
return this.config?.audio?.sample_rate ?? 22050;
|
|
32709
32801
|
}
|
|
32710
32802
|
dispose() {
|
|
@@ -32713,6 +32805,7 @@ var init_voice = __esm({
|
|
|
32713
32805
|
this.session = null;
|
|
32714
32806
|
this.ort = null;
|
|
32715
32807
|
this.config = null;
|
|
32808
|
+
this.mlxActive = false;
|
|
32716
32809
|
}
|
|
32717
32810
|
// -------------------------------------------------------------------------
|
|
32718
32811
|
// Text chunking for long TTS input
|
|
@@ -32775,6 +32868,10 @@ var init_voice = __esm({
|
|
|
32775
32868
|
// Synthesis pipeline
|
|
32776
32869
|
// -------------------------------------------------------------------------
|
|
32777
32870
|
async synthesizeAndPlay(text, volume = 1, pitchFactor = 1) {
|
|
32871
|
+
if (this.mlxActive) {
|
|
32872
|
+
await this.synthesizeWithMlx(text, volume, pitchFactor);
|
|
32873
|
+
return;
|
|
32874
|
+
}
|
|
32778
32875
|
if (!this.session || !this.config || !this.ort)
|
|
32779
32876
|
return;
|
|
32780
32877
|
const cleaned = text.replace(/\*/g, "");
|
|
@@ -33021,6 +33118,196 @@ var init_voice = __esm({
|
|
|
33021
33118
|
}
|
|
33022
33119
|
}
|
|
33023
33120
|
// -------------------------------------------------------------------------
|
|
33121
|
+
// MLX Audio backend (macOS Apple Silicon)
|
|
33122
|
+
// -------------------------------------------------------------------------
|
|
33123
|
+
/** Check if we're on macOS Apple Silicon */
|
|
33124
|
+
isMlxCapable() {
|
|
33125
|
+
return platform3() === "darwin" && process.arch === "arm64";
|
|
33126
|
+
}
|
|
33127
|
+
/** Resolve python3 binary path */
|
|
33128
|
+
findPython3() {
|
|
33129
|
+
if (this.python3Path)
|
|
33130
|
+
return this.python3Path;
|
|
33131
|
+
for (const bin of ["python3", "python"]) {
|
|
33132
|
+
try {
|
|
33133
|
+
const path = execSync27(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
33134
|
+
if (path) {
|
|
33135
|
+
this.python3Path = path;
|
|
33136
|
+
return path;
|
|
33137
|
+
}
|
|
33138
|
+
} catch {
|
|
33139
|
+
}
|
|
33140
|
+
}
|
|
33141
|
+
return null;
|
|
33142
|
+
}
|
|
33143
|
+
/** Check if mlx-audio is installed */
|
|
33144
|
+
checkMlxInstalled() {
|
|
33145
|
+
if (this.mlxInstalled !== null)
|
|
33146
|
+
return this.mlxInstalled;
|
|
33147
|
+
const py = this.findPython3();
|
|
33148
|
+
if (!py) {
|
|
33149
|
+
this.mlxInstalled = false;
|
|
33150
|
+
return false;
|
|
33151
|
+
}
|
|
33152
|
+
try {
|
|
33153
|
+
execSync27(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
|
|
33154
|
+
this.mlxInstalled = true;
|
|
33155
|
+
return true;
|
|
33156
|
+
} catch {
|
|
33157
|
+
this.mlxInstalled = false;
|
|
33158
|
+
return false;
|
|
33159
|
+
}
|
|
33160
|
+
}
|
|
33161
|
+
/**
|
|
33162
|
+
* Ensure mlx-audio is installed. Auto-installs via pip on first use.
|
|
33163
|
+
* Only works on macOS Apple Silicon.
|
|
33164
|
+
*/
|
|
33165
|
+
async ensureMlxAudio() {
|
|
33166
|
+
if (!this.isMlxCapable()) {
|
|
33167
|
+
throw new Error("MLX Audio requires macOS on Apple Silicon (M1/M2/M3/M4). Use an ONNX voice model instead: glados, overwatch");
|
|
33168
|
+
}
|
|
33169
|
+
const py = this.findPython3();
|
|
33170
|
+
if (!py) {
|
|
33171
|
+
throw new Error("python3 not found. Install Python 3.10+ to use MLX Audio voices. Try: brew install python@3.12");
|
|
33172
|
+
}
|
|
33173
|
+
if (this.checkMlxInstalled())
|
|
33174
|
+
return;
|
|
33175
|
+
renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
|
|
33176
|
+
try {
|
|
33177
|
+
execSync27(`${py} -m pip install mlx-audio --quiet`, {
|
|
33178
|
+
stdio: "pipe",
|
|
33179
|
+
timeout: 3e5
|
|
33180
|
+
// 5 min — may need to compile
|
|
33181
|
+
});
|
|
33182
|
+
this.mlxInstalled = true;
|
|
33183
|
+
renderInfo("MLX Audio installed successfully.");
|
|
33184
|
+
} catch (err) {
|
|
33185
|
+
try {
|
|
33186
|
+
execSync27(`${py} -m pip install mlx-audio --user --quiet`, {
|
|
33187
|
+
stdio: "pipe",
|
|
33188
|
+
timeout: 3e5
|
|
33189
|
+
});
|
|
33190
|
+
this.mlxInstalled = true;
|
|
33191
|
+
renderInfo("MLX Audio installed successfully (user site-packages).");
|
|
33192
|
+
} catch (err2) {
|
|
33193
|
+
throw new Error(`Failed to install mlx-audio. Try manually: pip install mlx-audio
|
|
33194
|
+
Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
33195
|
+
}
|
|
33196
|
+
}
|
|
33197
|
+
}
|
|
33198
|
+
/**
|
|
33199
|
+
* Synthesize and play audio using MLX Audio CLI.
|
|
33200
|
+
* Generates a WAV file via `python3 -m mlx_audio.tts.generate`, then plays it.
|
|
33201
|
+
*/
|
|
33202
|
+
async synthesizeWithMlx(text, volume = 1, _pitchFactor = 1) {
|
|
33203
|
+
const py = this.findPython3();
|
|
33204
|
+
if (!py)
|
|
33205
|
+
return;
|
|
33206
|
+
const cleaned = text.replace(/\*/g, "").trim();
|
|
33207
|
+
if (!cleaned)
|
|
33208
|
+
return;
|
|
33209
|
+
const model = VOICE_MODELS[this.modelId];
|
|
33210
|
+
if (!model)
|
|
33211
|
+
return;
|
|
33212
|
+
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
33213
|
+
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
33214
|
+
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
33215
|
+
const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
|
|
33216
|
+
const pyScript = [
|
|
33217
|
+
"import sys, json",
|
|
33218
|
+
"from mlx_audio.tts import generate as tts_gen",
|
|
33219
|
+
"text = json.loads(sys.argv[1])",
|
|
33220
|
+
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
33221
|
+
].join("; ");
|
|
33222
|
+
try {
|
|
33223
|
+
execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
33224
|
+
} catch (err) {
|
|
33225
|
+
try {
|
|
33226
|
+
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
33227
|
+
execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
33228
|
+
} catch (err2) {
|
|
33229
|
+
return;
|
|
33230
|
+
}
|
|
33231
|
+
}
|
|
33232
|
+
if (!existsSync31(wavPath))
|
|
33233
|
+
return;
|
|
33234
|
+
if (volume !== 1) {
|
|
33235
|
+
try {
|
|
33236
|
+
const wavData = readFileSync22(wavPath);
|
|
33237
|
+
if (wavData.length > 44) {
|
|
33238
|
+
const header = wavData.subarray(0, 44);
|
|
33239
|
+
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
33240
|
+
for (let i = 0; i < samples.length; i++) {
|
|
33241
|
+
samples[i] = Math.round(samples[i] * volume);
|
|
33242
|
+
}
|
|
33243
|
+
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
33244
|
+
writeFileSync11(wavPath, scaled);
|
|
33245
|
+
}
|
|
33246
|
+
} catch {
|
|
33247
|
+
}
|
|
33248
|
+
}
|
|
33249
|
+
if (this.onPCMOutput) {
|
|
33250
|
+
try {
|
|
33251
|
+
const wavData = readFileSync22(wavPath);
|
|
33252
|
+
if (wavData.length > 44) {
|
|
33253
|
+
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
33254
|
+
const sampleRate = wavData.readUInt32LE(24);
|
|
33255
|
+
this.onPCMOutput(pcm, sampleRate);
|
|
33256
|
+
}
|
|
33257
|
+
} catch {
|
|
33258
|
+
}
|
|
33259
|
+
}
|
|
33260
|
+
await this.playWav(wavPath);
|
|
33261
|
+
try {
|
|
33262
|
+
unlinkSync4(wavPath);
|
|
33263
|
+
} catch {
|
|
33264
|
+
}
|
|
33265
|
+
}
|
|
33266
|
+
/**
|
|
33267
|
+
* Synthesize text to a WAV buffer using MLX Audio (no playback).
|
|
33268
|
+
* Used by synthesizeToBuffer / synthesizeToPCM for MLX models.
|
|
33269
|
+
*/
|
|
33270
|
+
async synthesizeMlxToBuffer(text) {
|
|
33271
|
+
const py = this.findPython3();
|
|
33272
|
+
if (!py)
|
|
33273
|
+
return null;
|
|
33274
|
+
const cleaned = text.replace(/\*/g, "").trim();
|
|
33275
|
+
if (!cleaned)
|
|
33276
|
+
return null;
|
|
33277
|
+
const model = VOICE_MODELS[this.modelId];
|
|
33278
|
+
if (!model)
|
|
33279
|
+
return null;
|
|
33280
|
+
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
33281
|
+
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
33282
|
+
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
33283
|
+
const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
33284
|
+
const pyScript = [
|
|
33285
|
+
"import sys, json",
|
|
33286
|
+
"from mlx_audio.tts import generate as tts_gen",
|
|
33287
|
+
"text = json.loads(sys.argv[1])",
|
|
33288
|
+
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
33289
|
+
].join("; ");
|
|
33290
|
+
try {
|
|
33291
|
+
execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
33292
|
+
} catch {
|
|
33293
|
+
try {
|
|
33294
|
+
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
33295
|
+
execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
33296
|
+
} catch {
|
|
33297
|
+
return null;
|
|
33298
|
+
}
|
|
33299
|
+
}
|
|
33300
|
+
if (!existsSync31(wavPath))
|
|
33301
|
+
return null;
|
|
33302
|
+
try {
|
|
33303
|
+
const data = readFileSync22(wavPath);
|
|
33304
|
+
unlinkSync4(wavPath);
|
|
33305
|
+
return data;
|
|
33306
|
+
} catch {
|
|
33307
|
+
return null;
|
|
33308
|
+
}
|
|
33309
|
+
}
|
|
33310
|
+
// -------------------------------------------------------------------------
|
|
33024
33311
|
// Setup: ONNX runtime installation
|
|
33025
33312
|
// -------------------------------------------------------------------------
|
|
33026
33313
|
async ensureRuntime() {
|
|
@@ -38983,6 +39270,8 @@ var init_status_bar = __esm({
|
|
|
38983
39270
|
_currentFooterHeight = 5;
|
|
38984
39271
|
/** Timestamp when streaming started (for token rate calculation) */
|
|
38985
39272
|
_streamStartTime = 0;
|
|
39273
|
+
/** Current package version (shown in metrics row, rightmost) */
|
|
39274
|
+
_version = "";
|
|
38986
39275
|
/**
|
|
38987
39276
|
* Provide a callback that returns readline's current input state.
|
|
38988
39277
|
* StatusBar uses this to render typed text and position the cursor
|
|
@@ -39084,6 +39373,12 @@ var init_status_bar = __esm({
|
|
|
39084
39373
|
setContextWindowSize(size) {
|
|
39085
39374
|
this.metrics.contextWindowSize = size;
|
|
39086
39375
|
}
|
|
39376
|
+
/** Set the current package version for display in the metrics row */
|
|
39377
|
+
setVersion(version) {
|
|
39378
|
+
this._version = version;
|
|
39379
|
+
if (this.active)
|
|
39380
|
+
this.renderFooterPreserveCursor();
|
|
39381
|
+
}
|
|
39087
39382
|
/** Human expert speed ratio tracker */
|
|
39088
39383
|
_speedTracker = new HumanSpeedTracker();
|
|
39089
39384
|
/** Record a tool call for speed ratio tracking */
|
|
@@ -39530,6 +39825,12 @@ var init_status_bar = __esm({
|
|
|
39530
39825
|
const recW = 1 + 4 + (this._countdown > 0 ? 1 + `${this._countdown}s`.length : 0);
|
|
39531
39826
|
sections.push({ expanded: recStr, compact: recStr, expandedW: recW, compactW: recW, empty: false });
|
|
39532
39827
|
}
|
|
39828
|
+
if (this._version) {
|
|
39829
|
+
const vExpanded = pastel2(245, "v" + this._version);
|
|
39830
|
+
const vCompact = pastel2(245, "v" + this._version);
|
|
39831
|
+
const vW = 1 + this._version.length;
|
|
39832
|
+
sections.push({ expanded: vExpanded, compact: vCompact, expandedW: vW, compactW: vW, empty: false });
|
|
39833
|
+
}
|
|
39533
39834
|
const activeIndices = sections.map((s, i) => !s.empty ? i : -1).filter((i) => i >= 0);
|
|
39534
39835
|
const isCompact = new Array(sections.length).fill(false);
|
|
39535
39836
|
const calcTotalWidth = () => {
|
|
@@ -40648,6 +40949,7 @@ async function startInteractive(config, repoPath) {
|
|
|
40648
40949
|
});
|
|
40649
40950
|
}
|
|
40650
40951
|
const statusBar = new StatusBar();
|
|
40952
|
+
statusBar.setVersion(version);
|
|
40651
40953
|
if (process.stdout.isTTY) {
|
|
40652
40954
|
const scrollTop = carouselLines > 0 ? carouselLines + 1 : 1;
|
|
40653
40955
|
statusBar.activate(scrollTop);
|
|
@@ -40738,6 +41040,19 @@ async function startInteractive(config, repoPath) {
|
|
|
40738
41040
|
}).catch(() => {
|
|
40739
41041
|
});
|
|
40740
41042
|
}
|
|
41043
|
+
const AUTO_UPDATE_INTERVAL_MS = 30 * 60 * 1e3;
|
|
41044
|
+
const autoUpdateTimer = setInterval(() => {
|
|
41045
|
+
const updateMode = savedSettings.updateMode ?? "auto";
|
|
41046
|
+
if (updateMode === "manual")
|
|
41047
|
+
return;
|
|
41048
|
+
checkForUpdate(version).then((updateInfo) => {
|
|
41049
|
+
if (updateInfo) {
|
|
41050
|
+
performSilentUpdate();
|
|
41051
|
+
}
|
|
41052
|
+
}).catch(() => {
|
|
41053
|
+
});
|
|
41054
|
+
}, AUTO_UPDATE_INTERVAL_MS);
|
|
41055
|
+
autoUpdateTimer.unref();
|
|
40741
41056
|
const voiceEngine = new VoiceEngine();
|
|
40742
41057
|
let voiceSession = null;
|
|
40743
41058
|
let exposeGateway = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-agents-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.95.0",
|
|
4
4
|
"description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,7 +56,10 @@
|
|
|
56
56
|
"micropayments",
|
|
57
57
|
"factory-ai",
|
|
58
58
|
"droid",
|
|
59
|
-
"code-delegation"
|
|
59
|
+
"code-delegation",
|
|
60
|
+
"mlx-audio",
|
|
61
|
+
"apple-silicon",
|
|
62
|
+
"kokoro-tts"
|
|
60
63
|
],
|
|
61
64
|
"author": "robit-man",
|
|
62
65
|
"license": "MIT",
|