open-agents-ai 0.103.81 → 0.103.83
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 +136 -39
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1343,10 +1343,22 @@ var init_shell = __esm({
|
|
|
1343
1343
|
workingDir;
|
|
1344
1344
|
defaultTimeout;
|
|
1345
1345
|
_sudoPassword = null;
|
|
1346
|
+
/** Active child processes — killed on abort for instant /stop */
|
|
1347
|
+
_activeChildren = /* @__PURE__ */ new Set();
|
|
1346
1348
|
constructor(workingDir, defaultTimeout = 3e4) {
|
|
1347
1349
|
this.workingDir = workingDir;
|
|
1348
1350
|
this.defaultTimeout = defaultTimeout;
|
|
1349
1351
|
}
|
|
1352
|
+
/** Kill all active child processes immediately (called by /stop) */
|
|
1353
|
+
killAll() {
|
|
1354
|
+
for (const child of this._activeChildren) {
|
|
1355
|
+
try {
|
|
1356
|
+
child.kill("SIGKILL");
|
|
1357
|
+
} catch {
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
this._activeChildren.clear();
|
|
1361
|
+
}
|
|
1350
1362
|
/** Set a cached sudo password for the session. The shell tool will
|
|
1351
1363
|
* automatically retry permission-denied commands with `sudo -S`. */
|
|
1352
1364
|
setSudoPassword(password) {
|
|
@@ -1397,17 +1409,14 @@ ${stdinInput ?? ""}`);
|
|
|
1397
1409
|
cwd: this.workingDir,
|
|
1398
1410
|
env: {
|
|
1399
1411
|
...process.env,
|
|
1400
|
-
// Non-interactive mode: libraries like prompts, inquirer,
|
|
1401
|
-
// create-next-app, and many Node CLI tools check CI to skip
|
|
1402
|
-
// interactive prompts and use defaults instead.
|
|
1403
1412
|
CI: "true",
|
|
1404
1413
|
NONINTERACTIVE: "1",
|
|
1405
|
-
// Disable color in most tools to get clean output
|
|
1406
1414
|
NO_COLOR: "1",
|
|
1407
1415
|
FORCE_COLOR: "0"
|
|
1408
1416
|
},
|
|
1409
1417
|
stdio: ["pipe", "pipe", "pipe"]
|
|
1410
1418
|
});
|
|
1419
|
+
this._activeChildren.add(child);
|
|
1411
1420
|
let stdout = "";
|
|
1412
1421
|
let stderr = "";
|
|
1413
1422
|
let killed = false;
|
|
@@ -1450,6 +1459,7 @@ ${stdinInput ?? ""}`);
|
|
|
1450
1459
|
}
|
|
1451
1460
|
child.stdin.end();
|
|
1452
1461
|
child.on("exit", (code) => {
|
|
1462
|
+
this._activeChildren.delete(child);
|
|
1453
1463
|
exitFlushTimer = setTimeout(() => {
|
|
1454
1464
|
const durationMs = performance.now() - start;
|
|
1455
1465
|
if (killed) {
|
|
@@ -18628,6 +18638,7 @@ var init_agenticRunner = __esm({
|
|
|
18628
18638
|
handlers = [];
|
|
18629
18639
|
pendingUserMessages = [];
|
|
18630
18640
|
aborted = false;
|
|
18641
|
+
_abortController = new AbortController();
|
|
18631
18642
|
_paused = false;
|
|
18632
18643
|
_pauseResolve = null;
|
|
18633
18644
|
_sudoPassword = null;
|
|
@@ -18837,14 +18848,23 @@ ${this.options.dynamicContext}`,
|
|
|
18837
18848
|
injectUserMessage(content) {
|
|
18838
18849
|
this.pendingUserMessages.push(content);
|
|
18839
18850
|
}
|
|
18840
|
-
/** Abort the current task run */
|
|
18851
|
+
/** Abort the current task run — cancels in-flight requests and kills child processes */
|
|
18841
18852
|
abort() {
|
|
18842
18853
|
this.aborted = true;
|
|
18854
|
+
this._abortController.abort();
|
|
18855
|
+
const shellTool = this.tools.get("shell");
|
|
18856
|
+
if (shellTool && typeof shellTool.killAll === "function") {
|
|
18857
|
+
shellTool.killAll();
|
|
18858
|
+
}
|
|
18843
18859
|
if (this._pauseResolve) {
|
|
18844
18860
|
this._pauseResolve();
|
|
18845
18861
|
this._pauseResolve = null;
|
|
18846
18862
|
}
|
|
18847
18863
|
}
|
|
18864
|
+
/** Get the current abort signal for passing to fetch/spawn */
|
|
18865
|
+
get abortSignal() {
|
|
18866
|
+
return this._abortController.signal;
|
|
18867
|
+
}
|
|
18848
18868
|
/**
|
|
18849
18869
|
* Pause the current task gracefully. The run loop will suspend at the next
|
|
18850
18870
|
* turn boundary (between tool calls / model requests) without destroying state.
|
|
@@ -18955,6 +18975,11 @@ Respond with your assessment, then take action.`;
|
|
|
18955
18975
|
}
|
|
18956
18976
|
/** Run a task through the agentic loop */
|
|
18957
18977
|
async run(task, context) {
|
|
18978
|
+
this.aborted = false;
|
|
18979
|
+
this._abortController = new AbortController();
|
|
18980
|
+
if (typeof this.backend.setAbortSignal === "function") {
|
|
18981
|
+
this.backend.setAbortSignal(this._abortController.signal);
|
|
18982
|
+
}
|
|
18958
18983
|
const start = Date.now();
|
|
18959
18984
|
const taskTimeoutMs = this.options.taskTimeoutMs;
|
|
18960
18985
|
const selfEvalInterval = taskTimeoutMs;
|
|
@@ -19615,6 +19640,10 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
19615
19640
|
try {
|
|
19616
19641
|
response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
|
|
19617
19642
|
} catch (reqErr) {
|
|
19643
|
+
if (this.aborted || reqErr instanceof Error && reqErr.name === "AbortError") {
|
|
19644
|
+
this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
19645
|
+
break;
|
|
19646
|
+
}
|
|
19618
19647
|
const recovered = await this.retryOnTransient(reqErr, chatRequest, turn);
|
|
19619
19648
|
if (!recovered) {
|
|
19620
19649
|
const errMsg2 = reqErr instanceof Error ? reqErr.message : String(reqErr);
|
|
@@ -21004,12 +21033,18 @@ ${transcript}`
|
|
|
21004
21033
|
model;
|
|
21005
21034
|
apiKey;
|
|
21006
21035
|
thinking;
|
|
21036
|
+
/** Abort signal — set by the runner so /stop can cancel in-flight requests */
|
|
21037
|
+
_abortSignal = null;
|
|
21007
21038
|
constructor(baseUrl, model, apiKey, thinking) {
|
|
21008
21039
|
this.baseUrl = normalizeBaseUrl(baseUrl);
|
|
21009
21040
|
this.model = model;
|
|
21010
21041
|
this.apiKey = apiKey ?? "";
|
|
21011
21042
|
this.thinking = thinking ?? true;
|
|
21012
21043
|
}
|
|
21044
|
+
/** Set the abort signal from the runner (called at run start) */
|
|
21045
|
+
setAbortSignal(signal) {
|
|
21046
|
+
this._abortSignal = signal;
|
|
21047
|
+
}
|
|
21013
21048
|
/** Build auth headers — all providers use standard Bearer token auth. */
|
|
21014
21049
|
authHeaders() {
|
|
21015
21050
|
const headers = { "Content-Type": "application/json" };
|
|
@@ -21027,11 +21062,14 @@ ${transcript}`
|
|
|
21027
21062
|
max_tokens: request.maxTokens,
|
|
21028
21063
|
think: this.thinking
|
|
21029
21064
|
};
|
|
21030
|
-
const
|
|
21065
|
+
const fetchOpts = {
|
|
21031
21066
|
method: "POST",
|
|
21032
21067
|
headers: this.authHeaders(),
|
|
21033
21068
|
body: JSON.stringify(body)
|
|
21034
|
-
}
|
|
21069
|
+
};
|
|
21070
|
+
if (this._abortSignal)
|
|
21071
|
+
fetchOpts.signal = this._abortSignal;
|
|
21072
|
+
const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, fetchOpts);
|
|
21035
21073
|
if (!resp.ok) {
|
|
21036
21074
|
const text = await resp.text().catch(() => "");
|
|
21037
21075
|
const isHtml = text.trimStart().startsWith("<!") || text.trimStart().startsWith("<html");
|
|
@@ -21089,11 +21127,14 @@ ${transcript}`
|
|
|
21089
21127
|
stream_options: { include_usage: true },
|
|
21090
21128
|
think: this.thinking
|
|
21091
21129
|
};
|
|
21092
|
-
const
|
|
21130
|
+
const streamFetchOpts = {
|
|
21093
21131
|
method: "POST",
|
|
21094
21132
|
headers: this.authHeaders(),
|
|
21095
21133
|
body: JSON.stringify(body)
|
|
21096
|
-
}
|
|
21134
|
+
};
|
|
21135
|
+
if (this._abortSignal)
|
|
21136
|
+
streamFetchOpts.signal = this._abortSignal;
|
|
21137
|
+
const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, streamFetchOpts);
|
|
21097
21138
|
if (!resp.ok) {
|
|
21098
21139
|
const text = await resp.text().catch(() => "");
|
|
21099
21140
|
const isHtml = text.trimStart().startsWith("<!") || text.trimStart().startsWith("<html");
|
|
@@ -38670,6 +38711,8 @@ var init_voice = __esm({
|
|
|
38670
38711
|
await this.ensureLuxtts();
|
|
38671
38712
|
this.luxttsActive = true;
|
|
38672
38713
|
this.mlxActive = false;
|
|
38714
|
+
this.ensureLuxttsDaemon().catch(() => {
|
|
38715
|
+
});
|
|
38673
38716
|
} else if (isMlx) {
|
|
38674
38717
|
await this.ensureMlxAudio();
|
|
38675
38718
|
this.mlxActive = true;
|
|
@@ -38722,6 +38765,8 @@ var init_voice = __esm({
|
|
|
38722
38765
|
await this.ensureLuxtts();
|
|
38723
38766
|
this.luxttsActive = true;
|
|
38724
38767
|
this.mlxActive = false;
|
|
38768
|
+
this.ensureLuxttsDaemon().catch(() => {
|
|
38769
|
+
});
|
|
38725
38770
|
} else if (isMlx) {
|
|
38726
38771
|
await this.ensureMlxAudio();
|
|
38727
38772
|
this.mlxActive = true;
|
|
@@ -38747,9 +38792,19 @@ var init_voice = __esm({
|
|
|
38747
38792
|
* Returns status message.
|
|
38748
38793
|
*/
|
|
38749
38794
|
async setCloneVoice(audioPath) {
|
|
38750
|
-
|
|
38751
|
-
|
|
38795
|
+
let p = audioPath.trim();
|
|
38796
|
+
if (p.startsWith("'") && p.endsWith("'") || p.startsWith('"') && p.endsWith('"')) {
|
|
38797
|
+
p = p.slice(1, -1);
|
|
38798
|
+
}
|
|
38799
|
+
p = p.replace(/\\ /g, " ");
|
|
38800
|
+
if (p.startsWith("~/") || p === "~") {
|
|
38801
|
+
p = join43(homedir12(), p.slice(1));
|
|
38752
38802
|
}
|
|
38803
|
+
if (!existsSync34(p)) {
|
|
38804
|
+
return `File not found: ${p}
|
|
38805
|
+
(original input: ${audioPath})`;
|
|
38806
|
+
}
|
|
38807
|
+
audioPath = p;
|
|
38753
38808
|
const refsDir = luxttsCloneRefsDir();
|
|
38754
38809
|
if (!existsSync34(refsDir))
|
|
38755
38810
|
mkdirSync14(refsDir, { recursive: true });
|
|
@@ -39298,7 +39353,7 @@ var init_voice = __esm({
|
|
|
39298
39353
|
isMlxCapable() {
|
|
39299
39354
|
return platform3() === "darwin" && process.arch === "arm64";
|
|
39300
39355
|
}
|
|
39301
|
-
/** Resolve python3 binary path */
|
|
39356
|
+
/** Resolve python3 binary path (cached after first call) */
|
|
39302
39357
|
findPython3() {
|
|
39303
39358
|
if (this.python3Path)
|
|
39304
39359
|
return this.python3Path;
|
|
@@ -39314,6 +39369,52 @@ var init_voice = __esm({
|
|
|
39314
39369
|
}
|
|
39315
39370
|
return null;
|
|
39316
39371
|
}
|
|
39372
|
+
/** Async version of findPython3 — non-blocking */
|
|
39373
|
+
async findPython3Async() {
|
|
39374
|
+
if (this.python3Path)
|
|
39375
|
+
return this.python3Path;
|
|
39376
|
+
for (const bin of ["python3", "python"]) {
|
|
39377
|
+
try {
|
|
39378
|
+
const path = await this.asyncShell(`which ${bin}`, 5e3);
|
|
39379
|
+
if (path) {
|
|
39380
|
+
this.python3Path = path;
|
|
39381
|
+
return path;
|
|
39382
|
+
}
|
|
39383
|
+
} catch {
|
|
39384
|
+
}
|
|
39385
|
+
}
|
|
39386
|
+
return null;
|
|
39387
|
+
}
|
|
39388
|
+
/** Non-blocking shell execution — async alternative to execSync.
|
|
39389
|
+
* Returns stdout string on exit 0, rejects otherwise. */
|
|
39390
|
+
asyncShell(command, timeoutMs = 3e4) {
|
|
39391
|
+
return new Promise((resolve31, reject) => {
|
|
39392
|
+
const proc = nodeSpawn("sh", ["-c", command], {
|
|
39393
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
39394
|
+
cwd: tmpdir6()
|
|
39395
|
+
});
|
|
39396
|
+
let stdout = "";
|
|
39397
|
+
let stderr = "";
|
|
39398
|
+
proc.stdout.on("data", (d) => {
|
|
39399
|
+
stdout += d.toString();
|
|
39400
|
+
});
|
|
39401
|
+
proc.stderr.on("data", (d) => {
|
|
39402
|
+
stderr += d.toString();
|
|
39403
|
+
});
|
|
39404
|
+
proc.on("error", reject);
|
|
39405
|
+
const timer = setTimeout(() => {
|
|
39406
|
+
proc.kill("SIGKILL");
|
|
39407
|
+
reject(new Error(`Timeout after ${timeoutMs}ms`));
|
|
39408
|
+
}, timeoutMs);
|
|
39409
|
+
proc.on("close", (code) => {
|
|
39410
|
+
clearTimeout(timer);
|
|
39411
|
+
if (code === 0)
|
|
39412
|
+
resolve31(stdout.trim());
|
|
39413
|
+
else
|
|
39414
|
+
reject(new Error(stderr.slice(0, 300) || `Exit code ${code}`));
|
|
39415
|
+
});
|
|
39416
|
+
});
|
|
39417
|
+
}
|
|
39317
39418
|
/** Check if mlx-audio is installed */
|
|
39318
39419
|
checkMlxInstalled() {
|
|
39319
39420
|
if (this.mlxInstalled !== null)
|
|
@@ -39486,9 +39587,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39486
39587
|
* Ensure LuxTTS venv is created with all dependencies.
|
|
39487
39588
|
* On first run: creates venv, installs PyTorch + LuxTTS + deps (~5-15 min).
|
|
39488
39589
|
* Subsequent runs: checks venv exists and import works.
|
|
39590
|
+
* All shell commands use asyncShell — never blocks the event loop.
|
|
39489
39591
|
*/
|
|
39490
39592
|
async ensureLuxtts() {
|
|
39491
|
-
const py = this.
|
|
39593
|
+
const py = await this.findPython3Async();
|
|
39492
39594
|
if (!py) {
|
|
39493
39595
|
throw new Error("python3 not found. LuxTTS requires Python 3.10+. Try: apt install python3 / brew install python3");
|
|
39494
39596
|
}
|
|
@@ -39496,23 +39598,25 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39496
39598
|
const venvPy = luxttsVenvPy();
|
|
39497
39599
|
if (existsSync34(venvPy)) {
|
|
39498
39600
|
try {
|
|
39499
|
-
|
|
39601
|
+
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
39500
39602
|
let hasCudaSys = false;
|
|
39501
39603
|
try {
|
|
39502
|
-
|
|
39604
|
+
await this.asyncShell("nvidia-smi", 5e3);
|
|
39503
39605
|
hasCudaSys = true;
|
|
39504
39606
|
} catch {
|
|
39505
39607
|
}
|
|
39506
39608
|
if (hasCudaSys) {
|
|
39507
|
-
|
|
39508
|
-
const torchCheck = execSync27(`${venvPy} -c "import torch; print('cuda' if torch.cuda.is_available() else 'cpu')"`, { stdio: "pipe", timeout: 15e3 }).toString().trim();
|
|
39609
|
+
this.asyncShell(`${venvPy} -c "import torch; print('cuda' if torch.cuda.is_available() else 'cpu')"`, 15e3).then(async (torchCheck) => {
|
|
39509
39610
|
if (torchCheck === "cpu") {
|
|
39510
|
-
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support...");
|
|
39511
|
-
|
|
39512
|
-
|
|
39611
|
+
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
|
|
39612
|
+
try {
|
|
39613
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet --force-reinstall torch torchaudio --index-url https://download.pytorch.org/whl/cu124`, 6e5);
|
|
39614
|
+
renderInfo("PyTorch reinstalled with CUDA GPU support.");
|
|
39615
|
+
} catch {
|
|
39616
|
+
}
|
|
39513
39617
|
}
|
|
39514
|
-
}
|
|
39515
|
-
}
|
|
39618
|
+
}).catch(() => {
|
|
39619
|
+
});
|
|
39516
39620
|
}
|
|
39517
39621
|
this.writeLuxttsInferScript();
|
|
39518
39622
|
this.autoDetectCloneRef();
|
|
@@ -39525,27 +39629,24 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39525
39629
|
if (!existsSync34(venvDir)) {
|
|
39526
39630
|
renderInfo(" Creating Python virtual environment...");
|
|
39527
39631
|
try {
|
|
39528
|
-
|
|
39529
|
-
stdio: "pipe",
|
|
39530
|
-
timeout: 6e4
|
|
39531
|
-
});
|
|
39632
|
+
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
39532
39633
|
} catch (err) {
|
|
39533
39634
|
throw new Error(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
|
|
39534
39635
|
}
|
|
39535
39636
|
}
|
|
39536
39637
|
let hasCuda = false;
|
|
39537
39638
|
try {
|
|
39538
|
-
|
|
39639
|
+
await this.asyncShell("nvidia-smi", 5e3);
|
|
39539
39640
|
hasCuda = true;
|
|
39540
39641
|
} catch {
|
|
39541
39642
|
}
|
|
39542
39643
|
if (hasCuda) {
|
|
39543
39644
|
renderInfo(" Installing PyTorch (CUDA GPU)...");
|
|
39544
39645
|
try {
|
|
39545
|
-
|
|
39646
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio --index-url https://download.pytorch.org/whl/cu124`, 6e5);
|
|
39546
39647
|
} catch {
|
|
39547
39648
|
try {
|
|
39548
|
-
|
|
39649
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio`, 6e5);
|
|
39549
39650
|
} catch (err2) {
|
|
39550
39651
|
throw new Error(`Failed to install PyTorch (CUDA): ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39551
39652
|
}
|
|
@@ -39553,10 +39654,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39553
39654
|
} else {
|
|
39554
39655
|
renderInfo(" Installing PyTorch (CPU \u2014 no NVIDIA GPU detected)...");
|
|
39555
39656
|
try {
|
|
39556
|
-
|
|
39657
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio --index-url https://download.pytorch.org/whl/cpu`, 6e5);
|
|
39557
39658
|
} catch {
|
|
39558
39659
|
try {
|
|
39559
|
-
|
|
39660
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio`, 6e5);
|
|
39560
39661
|
} catch (err2) {
|
|
39561
39662
|
throw new Error(`Failed to install PyTorch: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39562
39663
|
}
|
|
@@ -39567,9 +39668,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39567
39668
|
renderInfo(" Cloning LuxTTS repository...");
|
|
39568
39669
|
try {
|
|
39569
39670
|
if (existsSync34(repoDir)) {
|
|
39570
|
-
|
|
39671
|
+
await this.asyncShell(`rm -rf ${JSON.stringify(repoDir)}`, 3e4);
|
|
39571
39672
|
}
|
|
39572
|
-
|
|
39673
|
+
await this.asyncShell(`git clone --depth 1 https://github.com/ysharma3501/LuxTTS.git ${JSON.stringify(repoDir)}`, 12e4);
|
|
39573
39674
|
} catch (err) {
|
|
39574
39675
|
throw new Error(`Failed to clone LuxTTS: ${err instanceof Error ? err.message : String(err)}`);
|
|
39575
39676
|
}
|
|
@@ -39577,19 +39678,15 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39577
39678
|
renderInfo(" Installing LuxTTS dependencies...");
|
|
39578
39679
|
const pipCmd = JSON.stringify(venvPy);
|
|
39579
39680
|
const installCmds = [
|
|
39580
|
-
// Core deps from requirements.txt
|
|
39581
39681
|
`${pipCmd} -m pip install --quiet lhotse huggingface_hub safetensors pydub onnxruntime librosa "transformers<=4.57.6" inflect numpy vocos "setuptools<81"`,
|
|
39582
|
-
// Tokenization deps (piper_phonemize from custom index, plus CJK support)
|
|
39583
39682
|
`${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`,
|
|
39584
39683
|
`${pipCmd} -m pip install --quiet jieba pypinyin cn2an`,
|
|
39585
|
-
// LinaCodec custom vocoder (required by Zipvoice)
|
|
39586
39684
|
`${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git"`,
|
|
39587
|
-
// Zipvoice package from the cloned repo (installs as 'zipvoice')
|
|
39588
39685
|
`${pipCmd} -m pip install --quiet -e ${JSON.stringify(repoDir)}`
|
|
39589
39686
|
];
|
|
39590
39687
|
for (const cmd of installCmds) {
|
|
39591
39688
|
try {
|
|
39592
|
-
|
|
39689
|
+
await this.asyncShell(cmd, 3e5);
|
|
39593
39690
|
} catch (err) {
|
|
39594
39691
|
const msg = err instanceof Error ? err.message : String(err);
|
|
39595
39692
|
if (msg.includes("piper") || msg.includes("LinaCodec")) {
|
|
@@ -39600,7 +39697,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39600
39697
|
}
|
|
39601
39698
|
}
|
|
39602
39699
|
try {
|
|
39603
|
-
|
|
39700
|
+
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${repoDir}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
39604
39701
|
} catch (err) {
|
|
39605
39702
|
throw new Error(`LuxTTS installed but import failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
39606
39703
|
}
|
package/package.json
CHANGED