open-agents-ai 0.27.0 → 0.29.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 +292 -82
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4019,7 +4019,7 @@ function ensureCommand(command) {
|
|
|
4019
4019
|
const result2 = {
|
|
4020
4020
|
available: false,
|
|
4021
4021
|
installed: false,
|
|
4022
|
-
error: `No supported package manager
|
|
4022
|
+
error: `No supported package manager detected \u2014 ${command} unavailable.`
|
|
4023
4023
|
};
|
|
4024
4024
|
_cache.set(command, result2);
|
|
4025
4025
|
return result2;
|
|
@@ -4029,7 +4029,7 @@ function ensureCommand(command) {
|
|
|
4029
4029
|
const result2 = {
|
|
4030
4030
|
available: false,
|
|
4031
4031
|
installed: false,
|
|
4032
|
-
error: `No package for ${command} on ${pm}
|
|
4032
|
+
error: `No package mapping for ${command} on ${pm} \u2014 cannot auto-install.`
|
|
4033
4033
|
};
|
|
4034
4034
|
_cache.set(command, result2);
|
|
4035
4035
|
return result2;
|
|
@@ -6474,6 +6474,17 @@ async function probeStation(endpoint) {
|
|
|
6474
6474
|
}
|
|
6475
6475
|
}
|
|
6476
6476
|
function findStationBinary() {
|
|
6477
|
+
const oaVenvPython = join15(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
|
|
6478
|
+
if (existsSync11(oaVenvPython)) {
|
|
6479
|
+
try {
|
|
6480
|
+
execSync10(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
|
|
6481
|
+
return oaVenvPython;
|
|
6482
|
+
} catch {
|
|
6483
|
+
}
|
|
6484
|
+
}
|
|
6485
|
+
const oaVenvBin = join15(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
|
|
6486
|
+
if (existsSync11(oaVenvBin))
|
|
6487
|
+
return oaVenvBin;
|
|
6477
6488
|
const thisDir = dirname4(fileURLToPath(import.meta.url));
|
|
6478
6489
|
const localVenvPaths = [
|
|
6479
6490
|
resolve15(thisDir, "../../../../.moondream-venv/bin/python"),
|
|
@@ -10402,32 +10413,31 @@ Rules:
|
|
|
10402
10413
|
* Build a self-eval prompt for the agent when approaching timeout.
|
|
10403
10414
|
* Returns the prompt to inject. The agent will respond with a plan.
|
|
10404
10415
|
*/
|
|
10405
|
-
|
|
10416
|
+
buildHealthCheckPrompt(elapsedMs2, toolCallCount, repetitionScore, checkNumber) {
|
|
10406
10417
|
const elapsedMin = (elapsedMs2 / 6e4).toFixed(1);
|
|
10407
|
-
const remainingMin = (remainingMs / 6e4).toFixed(1);
|
|
10408
10418
|
const stuckWarning = repetitionScore > 0.5 ? `
|
|
10409
10419
|
\u26A0 REPETITION DETECTED: Your recent tool calls are ${Math.round(repetitionScore * 100)}% repetitive. You may be stuck in a loop.` : "";
|
|
10410
|
-
return `[
|
|
10420
|
+
return `[HEALTH CHECK #${checkNumber} \u2014 Progress Assessment]
|
|
10411
10421
|
|
|
10412
|
-
You have been working for ${elapsedMin} minutes with ${toolCallCount} tool calls.
|
|
10422
|
+
You have been working for ${elapsedMin} minutes with ${toolCallCount} tool calls. There is no time limit \u2014 take as long as you need.${stuckWarning}
|
|
10413
10423
|
|
|
10414
|
-
|
|
10424
|
+
Briefly assess your situation and choose ONE action:
|
|
10415
10425
|
|
|
10416
|
-
1. CONTINUE \u2014 If you are making
|
|
10426
|
+
1. CONTINUE \u2014 If you are making progress, briefly note what you've done and what remains. Keep working.
|
|
10417
10427
|
|
|
10418
|
-
2. PIVOT \u2014 If your current approach isn't working,
|
|
10428
|
+
2. PIVOT \u2014 If your current approach isn't working, describe a different strategy and immediately try it.
|
|
10419
10429
|
|
|
10420
|
-
3. CHECKPOINT \u2014 If you've made partial progress
|
|
10430
|
+
3. CHECKPOINT \u2014 If you've made partial progress and want to save it, call task_complete with a summary. The user can continue later.
|
|
10421
10431
|
|
|
10422
|
-
Respond with your assessment, then take action
|
|
10432
|
+
Respond with your assessment, then take action.`;
|
|
10423
10433
|
}
|
|
10424
10434
|
/** Run a task through the agentic loop */
|
|
10425
10435
|
async run(task, context) {
|
|
10426
10436
|
const start = Date.now();
|
|
10427
10437
|
const taskTimeoutMs = this.options.taskTimeoutMs;
|
|
10428
|
-
const
|
|
10429
|
-
|
|
10430
|
-
let
|
|
10438
|
+
const selfEvalInterval = taskTimeoutMs;
|
|
10439
|
+
let nextSelfEval = start + selfEvalInterval;
|
|
10440
|
+
let selfEvalCount = 0;
|
|
10431
10441
|
const toolCallLog = [];
|
|
10432
10442
|
this.aborted = false;
|
|
10433
10443
|
this.pendingUserMessages.length = 0;
|
|
@@ -10456,24 +10466,20 @@ TASK: ${task}` : task }
|
|
|
10456
10466
|
break;
|
|
10457
10467
|
}
|
|
10458
10468
|
const now = Date.now();
|
|
10459
|
-
if (now >
|
|
10460
|
-
|
|
10461
|
-
break;
|
|
10462
|
-
}
|
|
10463
|
-
if (!softTimeoutTriggered && now > softDeadline) {
|
|
10464
|
-
softTimeoutTriggered = true;
|
|
10469
|
+
if (now > nextSelfEval) {
|
|
10470
|
+
selfEvalCount++;
|
|
10465
10471
|
const elapsed = now - start;
|
|
10466
|
-
const remaining = hardDeadline - now;
|
|
10467
10472
|
const repetitionScore = this.detectRepetition(toolCallLog);
|
|
10468
10473
|
this.emit({
|
|
10469
10474
|
type: "compaction",
|
|
10470
|
-
content: `
|
|
10475
|
+
content: `Health check #${selfEvalCount} (${(elapsed / 6e4).toFixed(1)}m elapsed) \u2014 assessing progress`,
|
|
10471
10476
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10472
10477
|
});
|
|
10473
10478
|
messages.push({
|
|
10474
10479
|
role: "user",
|
|
10475
|
-
content: this.
|
|
10480
|
+
content: this.buildHealthCheckPrompt(elapsed, toolCallCount, repetitionScore, selfEvalCount)
|
|
10476
10481
|
});
|
|
10482
|
+
nextSelfEval = now + selfEvalInterval;
|
|
10477
10483
|
}
|
|
10478
10484
|
while (this.pendingUserMessages.length > 0) {
|
|
10479
10485
|
const userMsg = this.pendingUserMessages.shift();
|
|
@@ -10682,7 +10688,7 @@ ${result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : resul
|
|
|
10682
10688
|
});
|
|
10683
10689
|
}
|
|
10684
10690
|
}
|
|
10685
|
-
while (!completed && !this.aborted && this.options.bruteForce && bruteForceCycle < this.options.bruteForceMaxCycles
|
|
10691
|
+
while (!completed && !this.aborted && this.options.bruteForce && bruteForceCycle < this.options.bruteForceMaxCycles) {
|
|
10686
10692
|
bruteForceCycle++;
|
|
10687
10693
|
const totalTurns = messages.filter((m) => m.role === "assistant").length;
|
|
10688
10694
|
this.emit({
|
|
@@ -10716,24 +10722,20 @@ You have ${this.options.maxTurns} more turns. Continue making progress. Call tas
|
|
|
10716
10722
|
break;
|
|
10717
10723
|
}
|
|
10718
10724
|
const bfNow = Date.now();
|
|
10719
|
-
if (bfNow >
|
|
10720
|
-
|
|
10721
|
-
break;
|
|
10722
|
-
}
|
|
10723
|
-
if (!softTimeoutTriggered && bfNow > softDeadline) {
|
|
10724
|
-
softTimeoutTriggered = true;
|
|
10725
|
+
if (bfNow > nextSelfEval) {
|
|
10726
|
+
selfEvalCount++;
|
|
10725
10727
|
const elapsed = bfNow - start;
|
|
10726
|
-
const remaining = hardDeadline - bfNow;
|
|
10727
10728
|
const repetitionScore = this.detectRepetition(toolCallLog);
|
|
10728
10729
|
this.emit({
|
|
10729
10730
|
type: "compaction",
|
|
10730
|
-
content: `
|
|
10731
|
+
content: `Health check #${selfEvalCount} (${(elapsed / 6e4).toFixed(1)}m elapsed) \u2014 assessing progress`,
|
|
10731
10732
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10732
10733
|
});
|
|
10733
10734
|
messages.push({
|
|
10734
10735
|
role: "user",
|
|
10735
|
-
content: this.
|
|
10736
|
+
content: this.buildHealthCheckPrompt(elapsed, toolCallCount, repetitionScore, selfEvalCount)
|
|
10736
10737
|
});
|
|
10738
|
+
nextSelfEval = bfNow + selfEvalInterval;
|
|
10737
10739
|
}
|
|
10738
10740
|
while (this.pendingUserMessages.length > 0) {
|
|
10739
10741
|
const userMsg = this.pendingUserMessages.shift();
|
|
@@ -11405,8 +11407,7 @@ ${newerSummary}` : newerSummary;
|
|
|
11405
11407
|
const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
11406
11408
|
method: "POST",
|
|
11407
11409
|
headers: this.authHeaders(),
|
|
11408
|
-
body: JSON.stringify(body)
|
|
11409
|
-
signal: AbortSignal.timeout(request.timeoutMs)
|
|
11410
|
+
body: JSON.stringify(body)
|
|
11410
11411
|
});
|
|
11411
11412
|
if (!resp.ok) {
|
|
11412
11413
|
const text = await resp.text().catch(() => "");
|
|
@@ -11466,8 +11467,7 @@ ${newerSummary}` : newerSummary;
|
|
|
11466
11467
|
const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
11467
11468
|
method: "POST",
|
|
11468
11469
|
headers: this.authHeaders(),
|
|
11469
|
-
body: JSON.stringify(body)
|
|
11470
|
-
signal: AbortSignal.timeout(request.timeoutMs)
|
|
11470
|
+
body: JSON.stringify(body)
|
|
11471
11471
|
});
|
|
11472
11472
|
if (!resp.ok) {
|
|
11473
11473
|
const text = await resp.text().catch(() => "");
|
|
@@ -14761,62 +14761,220 @@ function isFirstRun() {
|
|
|
14761
14761
|
return true;
|
|
14762
14762
|
}
|
|
14763
14763
|
}
|
|
14764
|
-
|
|
14765
|
-
const log = onInfo ?? (() => {
|
|
14766
|
-
});
|
|
14764
|
+
function hasCmd(cmd) {
|
|
14767
14765
|
try {
|
|
14768
|
-
execSync13(
|
|
14766
|
+
execSync13(`which ${cmd}`, { stdio: "pipe", timeout: 3e3 });
|
|
14767
|
+
return true;
|
|
14769
14768
|
} catch {
|
|
14770
|
-
|
|
14771
|
-
|
|
14772
|
-
|
|
14773
|
-
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
|
|
14769
|
+
return false;
|
|
14770
|
+
}
|
|
14771
|
+
}
|
|
14772
|
+
function detectPkgManager() {
|
|
14773
|
+
if (hasCmd("apt-get"))
|
|
14774
|
+
return "apt";
|
|
14775
|
+
if (hasCmd("dnf"))
|
|
14776
|
+
return "dnf";
|
|
14777
|
+
if (hasCmd("pacman"))
|
|
14778
|
+
return "pacman";
|
|
14779
|
+
if (hasCmd("brew"))
|
|
14780
|
+
return "brew";
|
|
14781
|
+
return null;
|
|
14782
|
+
}
|
|
14783
|
+
function getVenvDir() {
|
|
14784
|
+
return join22(homedir8(), ".open-agents", "venv");
|
|
14785
|
+
}
|
|
14786
|
+
function hasVenvModule() {
|
|
14787
|
+
try {
|
|
14788
|
+
execSync13("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
14789
|
+
return true;
|
|
14790
|
+
} catch {
|
|
14791
|
+
return false;
|
|
14792
|
+
}
|
|
14793
|
+
}
|
|
14794
|
+
function ensureVenv(log) {
|
|
14795
|
+
const venvDir = getVenvDir();
|
|
14796
|
+
const venvPip = join22(venvDir, "bin", "pip");
|
|
14797
|
+
if (existsSync15(venvPip))
|
|
14798
|
+
return venvDir;
|
|
14799
|
+
log("Creating Python venv for vision deps...");
|
|
14800
|
+
if (!hasCmd("python3")) {
|
|
14801
|
+
log("python3 not found \u2014 cannot create venv.");
|
|
14802
|
+
return null;
|
|
14803
|
+
}
|
|
14804
|
+
if (!hasVenvModule()) {
|
|
14805
|
+
log("python3 venv module not available \u2014 venv creation skipped.");
|
|
14806
|
+
return null;
|
|
14807
|
+
}
|
|
14808
|
+
try {
|
|
14809
|
+
mkdirSync7(join22(homedir8(), ".open-agents"), { recursive: true });
|
|
14810
|
+
execSync13(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
14811
|
+
execSync13(`"${join22(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
14812
|
+
stdio: "pipe",
|
|
14813
|
+
timeout: 6e4
|
|
14814
|
+
});
|
|
14815
|
+
log("Python venv created at ~/.open-agents/venv");
|
|
14816
|
+
return venvDir;
|
|
14817
|
+
} catch (err) {
|
|
14818
|
+
log(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
|
|
14819
|
+
return null;
|
|
14820
|
+
}
|
|
14821
|
+
}
|
|
14822
|
+
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
14823
|
+
try {
|
|
14824
|
+
execSync13(`sudo -n ${cmd}`, {
|
|
14825
|
+
stdio: "pipe",
|
|
14826
|
+
timeout: timeoutMs,
|
|
14827
|
+
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
14828
|
+
});
|
|
14829
|
+
return true;
|
|
14830
|
+
} catch {
|
|
14831
|
+
return false;
|
|
14832
|
+
}
|
|
14833
|
+
}
|
|
14834
|
+
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
14835
|
+
try {
|
|
14836
|
+
execSync13(`sudo -S ${cmd}`, {
|
|
14837
|
+
input: password + "\n",
|
|
14838
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
14839
|
+
timeout: timeoutMs,
|
|
14840
|
+
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
14841
|
+
});
|
|
14842
|
+
return true;
|
|
14843
|
+
} catch {
|
|
14844
|
+
return false;
|
|
14845
|
+
}
|
|
14846
|
+
}
|
|
14847
|
+
async function sudoInstall(cmd, getSudoPassword, log, cachedPasswordRef, timeoutMs = 12e4) {
|
|
14848
|
+
if (cachedPasswordRef.value) {
|
|
14849
|
+
if (runWithSudo(cmd, cachedPasswordRef.value, timeoutMs))
|
|
14850
|
+
return true;
|
|
14851
|
+
}
|
|
14852
|
+
if (trySudoPasswordless(cmd, timeoutMs))
|
|
14853
|
+
return true;
|
|
14854
|
+
const pw = await getSudoPassword();
|
|
14855
|
+
if (pw) {
|
|
14856
|
+
cachedPasswordRef.value = pw;
|
|
14857
|
+
if (runWithSudo(cmd, pw, timeoutMs))
|
|
14858
|
+
return true;
|
|
14859
|
+
log("Authentication failed \u2014 please re-enter password.");
|
|
14860
|
+
const pw2 = await getSudoPassword();
|
|
14861
|
+
if (pw2) {
|
|
14862
|
+
cachedPasswordRef.value = pw2;
|
|
14863
|
+
if (runWithSudo(cmd, pw2, timeoutMs))
|
|
14864
|
+
return true;
|
|
14865
|
+
}
|
|
14866
|
+
}
|
|
14867
|
+
return false;
|
|
14868
|
+
}
|
|
14869
|
+
async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
14870
|
+
const log = onInfo ?? (() => {
|
|
14871
|
+
});
|
|
14872
|
+
const cachedPasswordRef = { value: null };
|
|
14873
|
+
const getPassword = getSudoPassword ?? (() => Promise.resolve(null));
|
|
14874
|
+
if (!hasCmd("tesseract")) {
|
|
14875
|
+
const pm2 = detectPkgManager();
|
|
14876
|
+
if (pm2) {
|
|
14877
|
+
const pkgMap = {
|
|
14878
|
+
apt: { cmd: "apt-get install -y tesseract-ocr", needsSudo: true },
|
|
14879
|
+
dnf: { cmd: "dnf install -y tesseract", needsSudo: true },
|
|
14880
|
+
pacman: { cmd: "pacman -S --noconfirm tesseract", needsSudo: true },
|
|
14881
|
+
brew: { cmd: "brew install tesseract", needsSudo: false }
|
|
14882
|
+
};
|
|
14883
|
+
const pkg = pkgMap[pm2];
|
|
14884
|
+
if (pkg.needsSudo) {
|
|
14885
|
+
log("Installing tesseract-ocr...");
|
|
14886
|
+
const ok = await sudoInstall(pkg.cmd, getPassword, log, cachedPasswordRef);
|
|
14887
|
+
if (ok && hasCmd("tesseract")) {
|
|
14888
|
+
log("tesseract-ocr installed successfully.");
|
|
14889
|
+
} else {
|
|
14890
|
+
log("tesseract-ocr could not be installed \u2014 OCR features will be limited.");
|
|
14891
|
+
}
|
|
14892
|
+
} else {
|
|
14893
|
+
log("Installing tesseract-ocr...");
|
|
14780
14894
|
try {
|
|
14781
|
-
execSync13(cmd, { stdio: "pipe", timeout:
|
|
14782
|
-
|
|
14783
|
-
|
|
14895
|
+
execSync13(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
14896
|
+
if (hasCmd("tesseract")) {
|
|
14897
|
+
log("tesseract-ocr installed successfully.");
|
|
14898
|
+
} else {
|
|
14899
|
+
log("tesseract-ocr install completed but binary not found \u2014 OCR features will be limited.");
|
|
14900
|
+
}
|
|
14784
14901
|
} catch {
|
|
14902
|
+
log("tesseract-ocr could not be installed \u2014 OCR features will be limited.");
|
|
14785
14903
|
}
|
|
14786
14904
|
}
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
else
|
|
14790
|
-
log("Could not auto-install tesseract (install manually: sudo apt install tesseract-ocr)");
|
|
14791
|
-
} catch {
|
|
14905
|
+
} else {
|
|
14906
|
+
log("No supported package manager detected \u2014 tesseract OCR unavailable.");
|
|
14792
14907
|
}
|
|
14793
14908
|
}
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
14801
|
-
|
|
14802
|
-
|
|
14803
|
-
|
|
14804
|
-
|
|
14805
|
-
|
|
14909
|
+
const pm = detectPkgManager();
|
|
14910
|
+
if (!hasCmd("pip3") && !hasCmd("pip") && pm) {
|
|
14911
|
+
const pipCmds = {
|
|
14912
|
+
apt: "apt-get install -y python3-pip",
|
|
14913
|
+
dnf: "dnf install -y python3-pip"
|
|
14914
|
+
};
|
|
14915
|
+
const pipCmd = pipCmds[pm];
|
|
14916
|
+
if (pipCmd) {
|
|
14917
|
+
log("Installing python3-pip...");
|
|
14918
|
+
const ok = await sudoInstall(pipCmd, getPassword, log, cachedPasswordRef);
|
|
14919
|
+
if (!ok) {
|
|
14920
|
+
log("python3-pip could not be installed \u2014 moondream-station may be unavailable.");
|
|
14921
|
+
}
|
|
14922
|
+
}
|
|
14923
|
+
}
|
|
14924
|
+
if (hasCmd("python3") && !hasVenvModule() && pm) {
|
|
14925
|
+
const venvCmds = {
|
|
14926
|
+
apt: () => {
|
|
14806
14927
|
try {
|
|
14807
|
-
execSync13(
|
|
14808
|
-
|
|
14809
|
-
break;
|
|
14928
|
+
const pyVer = execSync13(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
14929
|
+
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
14810
14930
|
} catch {
|
|
14931
|
+
return "apt-get install -y python3-venv";
|
|
14932
|
+
}
|
|
14933
|
+
},
|
|
14934
|
+
dnf: () => "dnf install -y python3-venv"
|
|
14935
|
+
};
|
|
14936
|
+
const cmdFn = venvCmds[pm];
|
|
14937
|
+
if (cmdFn) {
|
|
14938
|
+
const cmd = cmdFn();
|
|
14939
|
+
if (cmd) {
|
|
14940
|
+
log("Installing python3-venv...");
|
|
14941
|
+
const ok = await sudoInstall(cmd, getPassword, log, cachedPasswordRef);
|
|
14942
|
+
if (!ok) {
|
|
14943
|
+
log("python3-venv could not be installed \u2014 moondream-station may be unavailable.");
|
|
14811
14944
|
}
|
|
14812
14945
|
}
|
|
14813
|
-
if (installed)
|
|
14814
|
-
log("moondream-station installed.");
|
|
14815
|
-
else
|
|
14816
|
-
log("Could not auto-install moondream-station (install manually: pip install moondream-station)");
|
|
14817
|
-
} catch {
|
|
14818
14946
|
}
|
|
14819
14947
|
}
|
|
14948
|
+
const venvDir = getVenvDir();
|
|
14949
|
+
const venvBin = join22(venvDir, "bin");
|
|
14950
|
+
const venvMoondream = join22(venvBin, "moondream-station");
|
|
14951
|
+
if (hasCmd("moondream-station") || existsSync15(venvMoondream)) {
|
|
14952
|
+
return;
|
|
14953
|
+
}
|
|
14954
|
+
const venv = ensureVenv(log);
|
|
14955
|
+
if (!venv) {
|
|
14956
|
+
log("Python venv unavailable \u2014 moondream-station will not be installed.");
|
|
14957
|
+
return;
|
|
14958
|
+
}
|
|
14959
|
+
const venvPip = join22(venvBin, "pip");
|
|
14960
|
+
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
14961
|
+
try {
|
|
14962
|
+
execSync13(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
14963
|
+
if (existsSync15(venvMoondream)) {
|
|
14964
|
+
log("moondream-station installed successfully.");
|
|
14965
|
+
} else {
|
|
14966
|
+
try {
|
|
14967
|
+
const check = execSync13(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
14968
|
+
if (check.includes("moondream")) {
|
|
14969
|
+
log("moondream-station package installed.");
|
|
14970
|
+
}
|
|
14971
|
+
} catch {
|
|
14972
|
+
log("moondream-station install completed.");
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
} catch (err) {
|
|
14976
|
+
log(`moondream-station install failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
14977
|
+
}
|
|
14820
14978
|
}
|
|
14821
14979
|
function expandedModelName(baseModel) {
|
|
14822
14980
|
return `open-agents-${baseModel.replace(":", "-").replace(/\./g, "")}`;
|
|
@@ -18825,9 +18983,28 @@ var init_status_bar = __esm({
|
|
|
18825
18983
|
this.metrics.totalTokens = update.totalTokens;
|
|
18826
18984
|
if (update.estimatedContextTokens !== void 0)
|
|
18827
18985
|
this.metrics.estimatedContextTokens = update.estimatedContextTokens;
|
|
18986
|
+
this._streamingTokens = 0;
|
|
18828
18987
|
if (this.active)
|
|
18829
18988
|
this.renderFooterPreserveCursor();
|
|
18830
18989
|
}
|
|
18990
|
+
/** Running count of tokens estimated during streaming (reset on authoritative updateMetrics) */
|
|
18991
|
+
_streamingTokens = 0;
|
|
18992
|
+
_streamThrottleTimer = null;
|
|
18993
|
+
/** Increment the live streaming token counter (throttled re-render at 100ms) */
|
|
18994
|
+
incrementStreamingTokens(count) {
|
|
18995
|
+
this._streamingTokens += count;
|
|
18996
|
+
if (!this._streamThrottleTimer && this.active) {
|
|
18997
|
+
this._streamThrottleTimer = setTimeout(() => {
|
|
18998
|
+
this._streamThrottleTimer = null;
|
|
18999
|
+
if (this.active)
|
|
19000
|
+
this.renderFooterPreserveCursor();
|
|
19001
|
+
}, 100);
|
|
19002
|
+
}
|
|
19003
|
+
}
|
|
19004
|
+
/** Get the effective completion tokens (authoritative + live streaming estimate) */
|
|
19005
|
+
get effectiveCompletionTokens() {
|
|
19006
|
+
return this.metrics.completionTokens + this._streamingTokens;
|
|
19007
|
+
}
|
|
18831
19008
|
/** Reset metrics (e.g. on session start) */
|
|
18832
19009
|
resetMetrics() {
|
|
18833
19010
|
this.metrics.promptTokens = 0;
|
|
@@ -18953,7 +19130,8 @@ var init_status_bar = __esm({
|
|
|
18953
19130
|
const pipe = pastel2(60, " \u2502 ");
|
|
18954
19131
|
const tokIn = m.promptTokens > 0 ? m.promptTokens.toLocaleString() : `~${Math.max(m.estimatedContextTokens, 0).toLocaleString()}`;
|
|
18955
19132
|
const tokInLabel = pastel2(117, "In: ") + c2.bold(tokIn);
|
|
18956
|
-
const
|
|
19133
|
+
const effectiveOut = this.effectiveCompletionTokens;
|
|
19134
|
+
const tokOut = effectiveOut > 0 ? effectiveOut.toLocaleString() : `~${Math.ceil(m.totalTokens > 0 ? m.totalTokens - m.promptTokens : m.estimatedContextTokens * 0.3).toLocaleString()}`;
|
|
18957
19135
|
const tokOutLabel = pastel2(151, "Out: ") + c2.bold(tokOut);
|
|
18958
19136
|
const ctxUsed = m.estimatedContextTokens;
|
|
18959
19137
|
const ctxTotal = m.contextWindowSize;
|
|
@@ -19336,7 +19514,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
19336
19514
|
streamEnabled: stream?.enabled ?? false,
|
|
19337
19515
|
bruteForce: bruteForce ?? true,
|
|
19338
19516
|
bruteForceMaxCycles: 100,
|
|
19339
|
-
// effectively unlimited — hard timeout
|
|
19517
|
+
// effectively unlimited — no hard timeout, agent runs until complete or aborted
|
|
19340
19518
|
contextWindowSize: contextWindowSize ?? 0
|
|
19341
19519
|
});
|
|
19342
19520
|
const tools = buildTools(repoRoot, config);
|
|
@@ -19425,6 +19603,10 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
19425
19603
|
if (stream?.enabled) {
|
|
19426
19604
|
stream.renderer.write(event.content ?? "", event.streamKind ?? "content");
|
|
19427
19605
|
}
|
|
19606
|
+
if (statusBar && event.content) {
|
|
19607
|
+
const estimatedNewTokens = Math.max(1, Math.ceil(event.content.length / 4));
|
|
19608
|
+
statusBar.incrementStreamingTokens(estimatedNewTokens);
|
|
19609
|
+
}
|
|
19428
19610
|
break;
|
|
19429
19611
|
case "stream_end":
|
|
19430
19612
|
if (stream?.enabled) {
|
|
@@ -19667,13 +19849,33 @@ async function startInteractive(config, repoPath) {
|
|
|
19667
19849
|
const sessionMetrics = new SessionMetrics();
|
|
19668
19850
|
const workEvaluator = new WorkEvaluator();
|
|
19669
19851
|
ensureTranscribeCliBackground();
|
|
19852
|
+
let depSudoResolver = null;
|
|
19853
|
+
let depSudoPromptPending = false;
|
|
19670
19854
|
ensureVisionDeps((msg) => {
|
|
19671
19855
|
if (statusBar?.isActive) {
|
|
19672
19856
|
statusBar.beginContentWrite();
|
|
19673
19857
|
renderInfo(msg);
|
|
19674
19858
|
statusBar.endContentWrite();
|
|
19675
19859
|
}
|
|
19676
|
-
})
|
|
19860
|
+
}, () => new Promise((resolve19) => {
|
|
19861
|
+
depSudoPromptPending = true;
|
|
19862
|
+
depSudoResolver = (pw) => {
|
|
19863
|
+
depSudoPromptPending = false;
|
|
19864
|
+
depSudoResolver = null;
|
|
19865
|
+
if (pw)
|
|
19866
|
+
sessionSudoPassword = pw;
|
|
19867
|
+
resolve19(pw);
|
|
19868
|
+
};
|
|
19869
|
+
if (statusBar?.isActive) {
|
|
19870
|
+
statusBar.beginContentWrite();
|
|
19871
|
+
}
|
|
19872
|
+
process.stdout.write(` ${c2.bold(c2.yellow("\u{1F511} Password needed for dependency install:"))}
|
|
19873
|
+
`);
|
|
19874
|
+
process.stdout.write(` ${c2.bold(c2.yellow("\u{1F511} Password:"))} `);
|
|
19875
|
+
if (statusBar?.isActive) {
|
|
19876
|
+
statusBar.endContentWrite();
|
|
19877
|
+
}
|
|
19878
|
+
})).catch(() => {
|
|
19677
19879
|
});
|
|
19678
19880
|
const voiceEngine = new VoiceEngine();
|
|
19679
19881
|
const streamRenderer = new StreamRenderer();
|
|
@@ -20070,6 +20272,14 @@ async function startInteractive(config, repoPath) {
|
|
|
20070
20272
|
}, 50);
|
|
20071
20273
|
});
|
|
20072
20274
|
async function processLine(input) {
|
|
20275
|
+
if (depSudoPromptPending && depSudoResolver) {
|
|
20276
|
+
const pw = input.trim();
|
|
20277
|
+
process.stdout.write(`\r\x1B[K ${c2.dim("\u{1F511} Password received")}
|
|
20278
|
+
`);
|
|
20279
|
+
depSudoResolver(pw || null);
|
|
20280
|
+
showPrompt();
|
|
20281
|
+
return;
|
|
20282
|
+
}
|
|
20073
20283
|
if (sudoPromptPending && activeTask) {
|
|
20074
20284
|
sudoPromptPending = false;
|
|
20075
20285
|
sessionSudoPassword = input;
|
package/package.json
CHANGED