open-agents-ai 0.187.229 → 0.187.231

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 +121 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -251346,7 +251346,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
251346
251346
  });
251347
251347
 
251348
251348
  // packages/execution/dist/tools/scheduler.js
251349
- import { execSync as execSync22, exec as execCb } from "node:child_process";
251349
+ import { execSync as execSync22, exec as execCb, spawnSync as spawnSync2 } from "node:child_process";
251350
251350
  import { readFile as readFile15, writeFile as writeFile17, mkdir as mkdir12 } from "node:fs/promises";
251351
251351
  import { resolve as resolve24, join as join37 } from "node:path";
251352
251352
  import { homedir as homedir10 } from "node:os";
@@ -251416,7 +251416,18 @@ function getCurrentCrontab() {
251416
251416
  }
251417
251417
  function writeCrontab(lines) {
251418
251418
  const content = lines.join("\n") + "\n";
251419
- execSync22(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
251419
+ const result = spawnSync2("crontab", ["-"], {
251420
+ input: content,
251421
+ stdio: ["pipe", "pipe", "pipe"],
251422
+ encoding: "utf8"
251423
+ });
251424
+ if (result.error) {
251425
+ throw new Error(`writeCrontab: ${result.error.message}`);
251426
+ }
251427
+ if (result.status !== 0) {
251428
+ const stderr = (result.stderr || "").toString().trim();
251429
+ throw new Error(`writeCrontab: crontab exited ${result.status}${stderr ? `: ${stderr}` : ""}`);
251430
+ }
251420
251431
  }
251421
251432
  function findOaBinary() {
251422
251433
  for (const cmd of ["oa", "open-agents"]) {
@@ -257631,7 +257642,7 @@ ${output}`, durationMs: performance.now() - start2 };
257631
257642
  });
257632
257643
 
257633
257644
  // packages/execution/dist/tools/gps-location.js
257634
- import { execSync as execSync36, spawnSync as spawnSync2 } from "node:child_process";
257645
+ import { execSync as execSync36, spawnSync as spawnSync3 } from "node:child_process";
257635
257646
  import { existsSync as existsSync35, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "node:fs";
257636
257647
  import { join as join50 } from "node:path";
257637
257648
  import { tmpdir as tmpdir13, homedir as homedir15 } from "node:os";
@@ -290797,6 +290808,25 @@ var init_status_bar = __esm({
290797
290808
  } else if (type === "release") {
290798
290809
  this._textSelection.onMouseRelease(row, col);
290799
290810
  this.repaintContent();
290811
+ if (this._textSelection.hasSelection) {
290812
+ try {
290813
+ const ok2 = this._textSelection.copyToClipboard();
290814
+ if (ok2) {
290815
+ const pos2 = this.rowPositions(termRows());
290816
+ if (pos2.metricsRow > 0) {
290817
+ const origWrite = this._origWrite ?? process.stdout.write.bind(process.stdout);
290818
+ origWrite(`\x1B[${pos2.metricsRow};1H\x1B[2K\x1B[38;5;${TEXT_PRIMARY}m ✓ Copied to clipboard\x1B[0m`);
290819
+ setTimeout(() => {
290820
+ try {
290821
+ this.renderFooterAndPositionInput();
290822
+ } catch {
290823
+ }
290824
+ }, 1200);
290825
+ }
290826
+ }
290827
+ } catch {
290828
+ }
290829
+ }
290800
290830
  }
290801
290831
  }
290802
290832
  /** Copy current selection to clipboard. Returns true if copied. */
@@ -300291,15 +300321,15 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
300291
300321
  renderInfo(" ARM device detected — installing build prerequisites then deps individually.");
300292
300322
  const isMac = process.platform === "darwin";
300293
300323
  try {
300294
- const { spawnSync: spawnSync3 } = await import("node:child_process");
300324
+ const { spawnSync: spawnSync4 } = await import("node:child_process");
300295
300325
  if (process.stdout.isTTY) {
300296
300326
  process.stdout.write("\x1B[?1002l\x1B[?1003l\x1B[?1006l");
300297
300327
  }
300298
300328
  if (isMac) {
300299
300329
  renderInfo(" macOS ARM detected — installing build deps via Homebrew...");
300300
- const brewCheck = spawnSync3("which", ["brew"], { stdio: "pipe", timeout: 5e3 });
300330
+ const brewCheck = spawnSync4("which", ["brew"], { stdio: "pipe", timeout: 5e3 });
300301
300331
  if (brewCheck.status === 0) {
300302
- const brewResult = spawnSync3("brew", ["install", "llvm", "gcc", "openblas", "libsndfile"], {
300332
+ const brewResult = spawnSync4("brew", ["install", "llvm", "gcc", "openblas", "libsndfile"], {
300303
300333
  stdio: "pipe",
300304
300334
  timeout: 3e5
300305
300335
  });
@@ -300308,11 +300338,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
300308
300338
  const { renderVerbose: renderVerbose2 } = await Promise.resolve().then(() => (init_render(), render_exports));
300309
300339
  renderVerbose2(brewResult.stderr.toString());
300310
300340
  }
300311
- const llvmPrefix = spawnSync3("brew", ["--prefix", "llvm"], { stdio: "pipe", timeout: 5e3 });
300341
+ const llvmPrefix = spawnSync4("brew", ["--prefix", "llvm"], { stdio: "pipe", timeout: 5e3 });
300312
300342
  if (llvmPrefix.stdout) {
300313
300343
  const prefix = llvmPrefix.stdout.toString().trim();
300314
300344
  process.env.LLVM_CONFIG = `${prefix}/bin/llvm-config`;
300315
- const openblas = spawnSync3("brew", ["--prefix", "openblas"], { stdio: "pipe", timeout: 5e3 });
300345
+ const openblas = spawnSync4("brew", ["--prefix", "openblas"], { stdio: "pipe", timeout: 5e3 });
300316
300346
  if (openblas.stdout) {
300317
300347
  const obPrefix = openblas.stdout.toString().trim();
300318
300348
  process.env.LDFLAGS = `${process.env.LDFLAGS ?? ""} -L${obPrefix}/lib`.trim();
@@ -300325,10 +300355,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
300325
300355
  }
300326
300356
  } else {
300327
300357
  renderInfo(" System build tools needed (llvm, gcc). Requesting sudo access...");
300328
- const sudoCheck = spawnSync3("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
300358
+ const sudoCheck = spawnSync4("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
300329
300359
  if (sudoCheck.status === 0) {
300330
300360
  renderInfo(" Installing system build dependencies (this may take a minute)...");
300331
- const aptResult = spawnSync3("sudo", [
300361
+ const aptResult = spawnSync4("sudo", [
300332
300362
  "apt-get",
300333
300363
  "install",
300334
300364
  "-y",
@@ -306567,8 +306597,8 @@ async function handleUpdate(subcommand, ctx3) {
306567
306597
  renderInfo("Enter your password if prompted...");
306568
306598
  safeWrite("\n");
306569
306599
  try {
306570
- const { spawnSync: spawnSync3 } = await import("node:child_process");
306571
- const sudoResult = spawnSync3("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
306600
+ const { spawnSync: spawnSync4 } = await import("node:child_process");
306601
+ const sudoResult = spawnSync4("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
306572
306602
  if (sudoResult.status !== 0) throw new Error("sudo failed");
306573
306603
  } catch {
306574
306604
  renderWarning("Could not acquire sudo credentials. Try: sudo npm i -g open-agents-ai");
@@ -314969,6 +314999,65 @@ var init_direct_input = __esm({
314969
314999
  }
314970
315000
  });
314971
315001
 
315002
+ // packages/cli/src/api/access-policy.ts
315003
+ function defaultAccessMode(bindHost) {
315004
+ if (bindHost === "0.0.0.0" || bindHost === "::" || bindHost === "::0") {
315005
+ return "lan";
315006
+ }
315007
+ return "loopback";
315008
+ }
315009
+ function resolveAccessMode(envValue, bindHost) {
315010
+ const v = (envValue || "").toLowerCase().trim();
315011
+ if (v === "loopback" || v === "lan" || v === "any") return v;
315012
+ return defaultAccessMode(bindHost);
315013
+ }
315014
+ function stripMappedPrefix(ip) {
315015
+ return ip.replace(/^::ffff:/i, "");
315016
+ }
315017
+ function isLoopbackIP(ip) {
315018
+ if (!ip) return false;
315019
+ const clean3 = stripMappedPrefix(ip);
315020
+ if (clean3 === "::1") return true;
315021
+ if (/^127\./.test(clean3)) return true;
315022
+ return false;
315023
+ }
315024
+ function isPrivateIP(ip) {
315025
+ if (!ip) return false;
315026
+ const clean3 = stripMappedPrefix(ip);
315027
+ if (/^10\./.test(clean3)) return true;
315028
+ if (/^192\.168\./.test(clean3)) return true;
315029
+ const m2 = /^172\.(\d{1,3})\./.exec(clean3);
315030
+ if (m2) {
315031
+ const second3 = parseInt(m2[1], 10);
315032
+ if (second3 >= 16 && second3 <= 31) return true;
315033
+ }
315034
+ if (/^169\.254\./.test(clean3)) return true;
315035
+ if (/^f[cd][0-9a-f]{2}:/i.test(clean3)) return true;
315036
+ if (/^fe[89ab][0-9a-f]:/i.test(clean3)) return true;
315037
+ return false;
315038
+ }
315039
+ function isAllowedIP(ip, mode) {
315040
+ if (mode === "any") return true;
315041
+ if (isLoopbackIP(ip)) return true;
315042
+ if (mode === "lan" && isPrivateIP(ip)) return true;
315043
+ return false;
315044
+ }
315045
+ function describeAccessMode(mode) {
315046
+ switch (mode) {
315047
+ case "loopback":
315048
+ return "loopback only";
315049
+ case "lan":
315050
+ return "loopback + RFC 1918";
315051
+ case "any":
315052
+ return "any — WIDE OPEN";
315053
+ }
315054
+ }
315055
+ var init_access_policy = __esm({
315056
+ "packages/cli/src/api/access-policy.ts"() {
315057
+ "use strict";
315058
+ }
315059
+ });
315060
+
314972
315061
  // packages/cli/src/api/audit-log.ts
314973
315062
  var audit_log_exports = {};
314974
315063
  __export(audit_log_exports, {
@@ -325781,7 +325870,7 @@ function startApiServer(options2 = {}) {
325781
325870
  if (options2.quiet) setQuiet(true);
325782
325871
  const log22 = options2.quiet ? (_msg) => {
325783
325872
  } : (msg) => process.stderr.write(msg);
325784
- let host = "127.0.0.1";
325873
+ let host = "0.0.0.0";
325785
325874
  let port = 11435;
325786
325875
  const envHost = process.env["OA_HOST"];
325787
325876
  if (envHost) {
@@ -325957,7 +326046,23 @@ function startApiServer(options2 = {}) {
325957
326046
  process.exit(1);
325958
326047
  }
325959
326048
  }
326049
+ const accessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
326050
+ let _accessRejected = 0;
325960
326051
  const handler = (req2, res) => {
326052
+ const rawIp = req2.socket?.remoteAddress ?? "";
326053
+ if (!isAllowedIP(rawIp, accessMode)) {
326054
+ _accessRejected++;
326055
+ metrics.totalErrors++;
326056
+ try {
326057
+ res.writeHead(403, { "Content-Type": "application/json" });
326058
+ res.end(JSON.stringify({
326059
+ error: "access_denied",
326060
+ message: `Address ${rawIp} is not in the allowed network (mode: ${accessMode}). Set OA_ACCESS=any to disable.`
326061
+ }));
326062
+ } catch {
326063
+ }
326064
+ return;
326065
+ }
325961
326066
  handleRequest(req2, res, ollamaUrl, verbose).catch((err) => {
325962
326067
  metrics.totalErrors++;
325963
326068
  try {
@@ -326028,6 +326133,8 @@ function startApiServer(options2 = {}) {
326028
326133
  `);
326029
326134
  const proto = useTls ? "https" : "http";
326030
326135
  log22(` Listening on ${proto}://${host}:${port}
326136
+ `);
326137
+ log22(` Access: ${accessMode} (${describeAccessMode(accessMode)})
326031
326138
  `);
326032
326139
  log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
326033
326140
  `);
@@ -326116,6 +326223,7 @@ var init_serve = __esm({
326116
326223
  "packages/cli/src/api/serve.ts"() {
326117
326224
  "use strict";
326118
326225
  init_config();
326226
+ init_access_policy();
326119
326227
  init_audit_log();
326120
326228
  init_task_manager_singleton();
326121
326229
  init_disk_task_output();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.229",
3
+ "version": "0.187.231",
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",