open-agents-ai 0.103.82 → 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 +124 -37
- 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;
|
|
@@ -39308,7 +39353,7 @@ var init_voice = __esm({
|
|
|
39308
39353
|
isMlxCapable() {
|
|
39309
39354
|
return platform3() === "darwin" && process.arch === "arm64";
|
|
39310
39355
|
}
|
|
39311
|
-
/** Resolve python3 binary path */
|
|
39356
|
+
/** Resolve python3 binary path (cached after first call) */
|
|
39312
39357
|
findPython3() {
|
|
39313
39358
|
if (this.python3Path)
|
|
39314
39359
|
return this.python3Path;
|
|
@@ -39324,6 +39369,52 @@ var init_voice = __esm({
|
|
|
39324
39369
|
}
|
|
39325
39370
|
return null;
|
|
39326
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
|
+
}
|
|
39327
39418
|
/** Check if mlx-audio is installed */
|
|
39328
39419
|
checkMlxInstalled() {
|
|
39329
39420
|
if (this.mlxInstalled !== null)
|
|
@@ -39496,9 +39587,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39496
39587
|
* Ensure LuxTTS venv is created with all dependencies.
|
|
39497
39588
|
* On first run: creates venv, installs PyTorch + LuxTTS + deps (~5-15 min).
|
|
39498
39589
|
* Subsequent runs: checks venv exists and import works.
|
|
39590
|
+
* All shell commands use asyncShell — never blocks the event loop.
|
|
39499
39591
|
*/
|
|
39500
39592
|
async ensureLuxtts() {
|
|
39501
|
-
const py = this.
|
|
39593
|
+
const py = await this.findPython3Async();
|
|
39502
39594
|
if (!py) {
|
|
39503
39595
|
throw new Error("python3 not found. LuxTTS requires Python 3.10+. Try: apt install python3 / brew install python3");
|
|
39504
39596
|
}
|
|
@@ -39506,23 +39598,25 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39506
39598
|
const venvPy = luxttsVenvPy();
|
|
39507
39599
|
if (existsSync34(venvPy)) {
|
|
39508
39600
|
try {
|
|
39509
|
-
|
|
39601
|
+
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
39510
39602
|
let hasCudaSys = false;
|
|
39511
39603
|
try {
|
|
39512
|
-
|
|
39604
|
+
await this.asyncShell("nvidia-smi", 5e3);
|
|
39513
39605
|
hasCudaSys = true;
|
|
39514
39606
|
} catch {
|
|
39515
39607
|
}
|
|
39516
39608
|
if (hasCudaSys) {
|
|
39517
|
-
|
|
39518
|
-
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) => {
|
|
39519
39610
|
if (torchCheck === "cpu") {
|
|
39520
|
-
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support...");
|
|
39521
|
-
|
|
39522
|
-
|
|
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
|
+
}
|
|
39523
39617
|
}
|
|
39524
|
-
}
|
|
39525
|
-
}
|
|
39618
|
+
}).catch(() => {
|
|
39619
|
+
});
|
|
39526
39620
|
}
|
|
39527
39621
|
this.writeLuxttsInferScript();
|
|
39528
39622
|
this.autoDetectCloneRef();
|
|
@@ -39535,27 +39629,24 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39535
39629
|
if (!existsSync34(venvDir)) {
|
|
39536
39630
|
renderInfo(" Creating Python virtual environment...");
|
|
39537
39631
|
try {
|
|
39538
|
-
|
|
39539
|
-
stdio: "pipe",
|
|
39540
|
-
timeout: 6e4
|
|
39541
|
-
});
|
|
39632
|
+
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
39542
39633
|
} catch (err) {
|
|
39543
39634
|
throw new Error(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
|
|
39544
39635
|
}
|
|
39545
39636
|
}
|
|
39546
39637
|
let hasCuda = false;
|
|
39547
39638
|
try {
|
|
39548
|
-
|
|
39639
|
+
await this.asyncShell("nvidia-smi", 5e3);
|
|
39549
39640
|
hasCuda = true;
|
|
39550
39641
|
} catch {
|
|
39551
39642
|
}
|
|
39552
39643
|
if (hasCuda) {
|
|
39553
39644
|
renderInfo(" Installing PyTorch (CUDA GPU)...");
|
|
39554
39645
|
try {
|
|
39555
|
-
|
|
39646
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio --index-url https://download.pytorch.org/whl/cu124`, 6e5);
|
|
39556
39647
|
} catch {
|
|
39557
39648
|
try {
|
|
39558
|
-
|
|
39649
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio`, 6e5);
|
|
39559
39650
|
} catch (err2) {
|
|
39560
39651
|
throw new Error(`Failed to install PyTorch (CUDA): ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39561
39652
|
}
|
|
@@ -39563,10 +39654,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39563
39654
|
} else {
|
|
39564
39655
|
renderInfo(" Installing PyTorch (CPU \u2014 no NVIDIA GPU detected)...");
|
|
39565
39656
|
try {
|
|
39566
|
-
|
|
39657
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio --index-url https://download.pytorch.org/whl/cpu`, 6e5);
|
|
39567
39658
|
} catch {
|
|
39568
39659
|
try {
|
|
39569
|
-
|
|
39660
|
+
await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet torch torchaudio`, 6e5);
|
|
39570
39661
|
} catch (err2) {
|
|
39571
39662
|
throw new Error(`Failed to install PyTorch: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39572
39663
|
}
|
|
@@ -39577,9 +39668,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39577
39668
|
renderInfo(" Cloning LuxTTS repository...");
|
|
39578
39669
|
try {
|
|
39579
39670
|
if (existsSync34(repoDir)) {
|
|
39580
|
-
|
|
39671
|
+
await this.asyncShell(`rm -rf ${JSON.stringify(repoDir)}`, 3e4);
|
|
39581
39672
|
}
|
|
39582
|
-
|
|
39673
|
+
await this.asyncShell(`git clone --depth 1 https://github.com/ysharma3501/LuxTTS.git ${JSON.stringify(repoDir)}`, 12e4);
|
|
39583
39674
|
} catch (err) {
|
|
39584
39675
|
throw new Error(`Failed to clone LuxTTS: ${err instanceof Error ? err.message : String(err)}`);
|
|
39585
39676
|
}
|
|
@@ -39587,19 +39678,15 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39587
39678
|
renderInfo(" Installing LuxTTS dependencies...");
|
|
39588
39679
|
const pipCmd = JSON.stringify(venvPy);
|
|
39589
39680
|
const installCmds = [
|
|
39590
|
-
// Core deps from requirements.txt
|
|
39591
39681
|
`${pipCmd} -m pip install --quiet lhotse huggingface_hub safetensors pydub onnxruntime librosa "transformers<=4.57.6" inflect numpy vocos "setuptools<81"`,
|
|
39592
|
-
// Tokenization deps (piper_phonemize from custom index, plus CJK support)
|
|
39593
39682
|
`${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`,
|
|
39594
39683
|
`${pipCmd} -m pip install --quiet jieba pypinyin cn2an`,
|
|
39595
|
-
// LinaCodec custom vocoder (required by Zipvoice)
|
|
39596
39684
|
`${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git"`,
|
|
39597
|
-
// Zipvoice package from the cloned repo (installs as 'zipvoice')
|
|
39598
39685
|
`${pipCmd} -m pip install --quiet -e ${JSON.stringify(repoDir)}`
|
|
39599
39686
|
];
|
|
39600
39687
|
for (const cmd of installCmds) {
|
|
39601
39688
|
try {
|
|
39602
|
-
|
|
39689
|
+
await this.asyncShell(cmd, 3e5);
|
|
39603
39690
|
} catch (err) {
|
|
39604
39691
|
const msg = err instanceof Error ? err.message : String(err);
|
|
39605
39692
|
if (msg.includes("piper") || msg.includes("LinaCodec")) {
|
|
@@ -39610,7 +39697,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
39610
39697
|
}
|
|
39611
39698
|
}
|
|
39612
39699
|
try {
|
|
39613
|
-
|
|
39700
|
+
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${repoDir}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
39614
39701
|
} catch (err) {
|
|
39615
39702
|
throw new Error(`LuxTTS installed but import failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
39616
39703
|
}
|
package/package.json
CHANGED