open-agents-ai 0.101.0 → 0.101.1

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.
Files changed (2) hide show
  1. package/dist/index.js +95 -114
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29251,30 +29251,51 @@ function runWithSudo(cmd, password, timeoutMs = 12e4) {
29251
29251
  timeout: timeoutMs,
29252
29252
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
29253
29253
  });
29254
- return true;
29255
- } catch {
29256
- return false;
29254
+ return "ok";
29255
+ } catch (err) {
29256
+ const stderr = err?.stderr?.toString() ?? "";
29257
+ if (/incorrect password|authentication failure|Sorry, try again|not in the sudoers/i.test(stderr)) {
29258
+ return "auth_fail";
29259
+ }
29260
+ return "cmd_fail";
29257
29261
  }
29258
29262
  }
29259
- async function sudoInstall(cmd, getSudoPassword, log, cachedPasswordRef, timeoutMs = 12e4) {
29260
- if (cachedPasswordRef.value) {
29261
- if (runWithSudo(cmd, cachedPasswordRef.value, timeoutMs))
29262
- return true;
29263
+ function validateSudoPassword(password) {
29264
+ return runWithSudo("true", password, 1e4) === "ok";
29265
+ }
29266
+ async function acquireSudoPassword(getSudoPassword, log, cachedPasswordRef) {
29267
+ if (cachedPasswordRef.value && validateSudoPassword(cachedPasswordRef.value)) {
29268
+ return cachedPasswordRef.value;
29263
29269
  }
29270
+ if (trySudoPasswordless("true", 1e4)) {
29271
+ return "";
29272
+ }
29273
+ for (let attempt = 0; attempt < 2; attempt++) {
29274
+ if (attempt > 0)
29275
+ log("Authentication failed \u2014 please re-enter password.");
29276
+ const pw = await getSudoPassword();
29277
+ if (!pw)
29278
+ return null;
29279
+ if (validateSudoPassword(pw)) {
29280
+ cachedPasswordRef.value = pw;
29281
+ return pw;
29282
+ }
29283
+ }
29284
+ return null;
29285
+ }
29286
+ async function sudoInstall(cmd, getSudoPassword, log, cachedPasswordRef, timeoutMs = 12e4) {
29264
29287
  if (trySudoPasswordless(cmd, timeoutMs))
29265
29288
  return true;
29266
- const pw = await getSudoPassword();
29267
- if (pw) {
29268
- cachedPasswordRef.value = pw;
29269
- if (runWithSudo(cmd, pw, timeoutMs))
29270
- return true;
29271
- log("Authentication failed \u2014 please re-enter password.");
29272
- const pw2 = await getSudoPassword();
29273
- if (pw2) {
29274
- cachedPasswordRef.value = pw2;
29275
- if (runWithSudo(cmd, pw2, timeoutMs))
29276
- return true;
29277
- }
29289
+ const pw = await acquireSudoPassword(getSudoPassword, log, cachedPasswordRef);
29290
+ if (pw === null)
29291
+ return false;
29292
+ if (pw === "")
29293
+ return false;
29294
+ const result = runWithSudo(cmd, pw, timeoutMs);
29295
+ if (result === "ok")
29296
+ return true;
29297
+ if (result === "cmd_fail") {
29298
+ log(`Install command failed (not an auth issue) \u2014 package may not be available for this OS.`);
29278
29299
  }
29279
29300
  return false;
29280
29301
  }
@@ -29283,108 +29304,68 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29283
29304
  });
29284
29305
  const cachedPasswordRef = { value: null };
29285
29306
  const getPassword = getSudoPassword ?? (() => Promise.resolve(null));
29286
- if (!hasCmd("tesseract")) {
29287
- const pm2 = detectPkgManager();
29288
- if (pm2) {
29289
- const pkgMap = {
29290
- apt: { cmd: "apt-get install -y tesseract-ocr", needsSudo: true },
29291
- dnf: { cmd: "dnf install -y tesseract", needsSudo: true },
29292
- pacman: { cmd: "pacman -S --noconfirm tesseract", needsSudo: true },
29293
- brew: { cmd: "brew install tesseract", needsSudo: false },
29294
- choco: { cmd: "choco install -y tesseract", needsSudo: false }
29295
- };
29296
- const pkg = pkgMap[pm2];
29297
- if (pkg.needsSudo) {
29298
- log("Installing tesseract-ocr...");
29299
- const ok = await sudoInstall(pkg.cmd, getPassword, log, cachedPasswordRef);
29300
- if (ok && hasCmd("tesseract")) {
29301
- log("tesseract-ocr installed successfully.");
29302
- } else {
29303
- log("tesseract-ocr could not be installed \u2014 OCR features will be limited.");
29304
- }
29305
- } else {
29306
- log("Installing tesseract-ocr...");
29307
- try {
29308
- execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
29309
- if (hasCmd("tesseract")) {
29310
- log("tesseract-ocr installed successfully.");
29311
- } else {
29312
- log("tesseract-ocr install completed but binary not found \u2014 OCR features will be limited.");
29313
- }
29314
- } catch {
29315
- log("tesseract-ocr could not be installed \u2014 OCR features will be limited.");
29316
- }
29317
- }
29318
- } else {
29319
- log("No supported package manager detected \u2014 tesseract OCR unavailable.");
29320
- }
29321
- }
29322
- const pdfDeps = [
29323
- {
29324
- binary: "pdftotext",
29325
- label: "poppler-utils (pdftotext)",
29326
- pkgMap: {
29327
- apt: { cmd: "apt-get install -y poppler-utils", needsSudo: true },
29328
- dnf: { cmd: "dnf install -y poppler-utils", needsSudo: true },
29329
- pacman: { cmd: "pacman -S --noconfirm poppler", needsSudo: true },
29330
- brew: { cmd: "brew install poppler", needsSudo: false },
29331
- choco: { cmd: "choco install -y poppler", needsSudo: false }
29332
- }
29333
- },
29334
- {
29335
- binary: "gs",
29336
- label: "ghostscript",
29337
- pkgMap: {
29338
- apt: { cmd: "apt-get install -y ghostscript", needsSudo: true },
29339
- dnf: { cmd: "dnf install -y ghostscript", needsSudo: true },
29340
- pacman: { cmd: "pacman -S --noconfirm ghostscript", needsSudo: true },
29341
- brew: { cmd: "brew install ghostscript", needsSudo: false },
29342
- choco: { cmd: "choco install -y ghostscript", needsSudo: false }
29343
- }
29344
- },
29345
- {
29346
- binary: "ocrmypdf",
29347
- label: "ocrmypdf",
29348
- pkgMap: {
29349
- apt: { cmd: "apt-get install -y ocrmypdf", needsSudo: true },
29350
- dnf: { cmd: "dnf install -y ocrmypdf", needsSudo: true },
29351
- pacman: { cmd: "pacman -S --noconfirm ocrmypdf", needsSudo: true },
29352
- brew: { cmd: "brew install ocrmypdf", needsSudo: false },
29353
- choco: { cmd: "choco install -y ocrmypdf", needsSudo: false }
29354
- }
29355
- }
29307
+ const allDeps = [
29308
+ { binary: "tesseract", label: "tesseract-ocr", pkgs: { apt: "tesseract-ocr", dnf: "tesseract", pacman: "tesseract", brew: "tesseract", choco: "tesseract" } },
29309
+ { binary: "pdftotext", label: "poppler-utils", pkgs: { apt: "poppler-utils", dnf: "poppler-utils", pacman: "poppler", brew: "poppler", choco: "poppler" } },
29310
+ { binary: "gs", label: "ghostscript", pkgs: { apt: "ghostscript", dnf: "ghostscript", pacman: "ghostscript", brew: "ghostscript", choco: "ghostscript" } },
29311
+ { binary: "ocrmypdf", label: "ocrmypdf", pkgs: { apt: "ocrmypdf", dnf: "ocrmypdf", pacman: "ocrmypdf", brew: "ocrmypdf", choco: "ocrmypdf" } }
29356
29312
  ];
29357
29313
  {
29358
29314
  const pm2 = detectPkgManager();
29359
- for (const dep of pdfDeps) {
29360
- if (hasCmd(dep.binary))
29361
- continue;
29362
- if (!pm2) {
29363
- log(`No supported package manager detected \u2014 ${dep.label} unavailable.`);
29364
- continue;
29365
- }
29366
- const pkg = dep.pkgMap[pm2];
29367
- if (!pkg)
29368
- continue;
29369
- if (pkg.needsSudo) {
29370
- log(`Installing ${dep.label}...`);
29371
- const ok = await sudoInstall(pkg.cmd, getPassword, log, cachedPasswordRef);
29372
- if (ok && hasCmd(dep.binary)) {
29373
- log(`${dep.label} installed successfully.`);
29315
+ const missing = allDeps.filter((d) => !hasCmd(d.binary));
29316
+ if (missing.length === 0) {
29317
+ } else if (!pm2) {
29318
+ for (const d of missing)
29319
+ log(`No supported package manager \u2014 ${d.label} unavailable.`);
29320
+ } else {
29321
+ const pkgNames = missing.map((d) => d.pkgs[pm2]).filter(Boolean);
29322
+ if (pkgNames.length === 0) {
29323
+ for (const d of missing)
29324
+ log(`${d.label} not available for ${pm2}.`);
29325
+ } else {
29326
+ const labels = missing.map((d) => d.label).join(", ");
29327
+ log(`Installing ${labels}...`);
29328
+ const needsSudo = pm2 !== "brew" && pm2 !== "choco";
29329
+ let batchCmd;
29330
+ switch (pm2) {
29331
+ case "apt":
29332
+ batchCmd = `apt-get update -qq && apt-get install -y -qq ${pkgNames.join(" ")}`;
29333
+ break;
29334
+ case "dnf":
29335
+ batchCmd = `dnf install -y -q ${pkgNames.join(" ")}`;
29336
+ break;
29337
+ case "pacman":
29338
+ batchCmd = `pacman -S --noconfirm ${pkgNames.join(" ")}`;
29339
+ break;
29340
+ case "brew":
29341
+ batchCmd = `brew install ${pkgNames.join(" ")}`;
29342
+ break;
29343
+ case "choco":
29344
+ batchCmd = `choco install -y ${pkgNames.join(" ")}`;
29345
+ break;
29346
+ default:
29347
+ batchCmd = `echo "unsupported pm: ${pm2}" && exit 1`;
29348
+ break;
29349
+ }
29350
+ let ok = false;
29351
+ if (needsSudo) {
29352
+ ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
29374
29353
  } else {
29375
- log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
29354
+ try {
29355
+ execSync25(batchCmd, { stdio: "pipe", timeout: 18e4 });
29356
+ ok = true;
29357
+ } catch {
29358
+ ok = false;
29359
+ }
29376
29360
  }
29377
- } else {
29378
- log(`Installing ${dep.label}...`);
29379
- try {
29380
- execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
29381
- if (hasCmd(dep.binary)) {
29382
- log(`${dep.label} installed successfully.`);
29361
+ for (const d of missing) {
29362
+ if (hasCmd(d.binary)) {
29363
+ log(`${d.label} installed.`);
29364
+ } else if (!ok) {
29365
+ log(`${d.label} could not be installed \u2014 features will be limited.`);
29383
29366
  } else {
29384
- log(`${dep.label} install completed but binary not found.`);
29367
+ log(`${d.label} install completed but binary not found.`);
29385
29368
  }
29386
- } catch {
29387
- log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
29388
29369
  }
29389
29370
  }
29390
29371
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.101.0",
3
+ "version": "0.101.1",
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",