open-agents-ai 0.187.364 → 0.187.365

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 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -544461,11 +544461,31 @@ async function handleSlashCommand(input, ctx3) {
544461
544461
  } else {
544462
544462
  ctx4.saveSettings({ oaAccess: val2 });
544463
544463
  }
544464
- const { stopDaemon: stopDaemon3, ensureDaemon: ensureDaemon3 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
544465
- stopDaemon3();
544466
- await new Promise((r2) => setTimeout(r2, 800));
544467
- const ok3 = await ensureDaemon3();
544468
- renderInfo2(ok3 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
544464
+ const port2 = parseInt(process.env["OA_PORT"] || "11435", 10);
544465
+ let switched2 = false;
544466
+ try {
544467
+ const resp = await fetch(`http://127.0.0.1:${port2}/v1/admin/access`, {
544468
+ method: "POST",
544469
+ headers: { "Content-Type": "application/json" },
544470
+ body: JSON.stringify({ mode: val2 }),
544471
+ signal: AbortSignal.timeout(3e3)
544472
+ });
544473
+ switched2 = resp.ok;
544474
+ } catch {
544475
+ }
544476
+ if (switched2) {
544477
+ renderInfo2(`Access policy now '${val2}' (live, no restart). Persisted to ~/.open-agents/access.`);
544478
+ } else {
544479
+ const { stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2, isDaemonRunning: isDaemonRunning2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
544480
+ stopDaemon2();
544481
+ const deadline = Date.now() + 4e3;
544482
+ while (Date.now() < deadline) {
544483
+ if (!await isDaemonRunning2(port2)) break;
544484
+ await new Promise((r2) => setTimeout(r2, 200));
544485
+ }
544486
+ const ok2 = await ensureDaemon2();
544487
+ renderInfo2(ok2 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
544488
+ }
544469
544489
  return "handled";
544470
544490
  }
544471
544491
  });
@@ -544506,11 +544526,36 @@ async function handleSlashCommand(input, ctx3) {
544506
544526
  } else {
544507
544527
  ctx3.saveSettings({ oaAccess: val });
544508
544528
  }
544509
- const { stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
544510
- stopDaemon2();
544511
- await new Promise((r2) => setTimeout(r2, 800));
544512
- const ok2 = await ensureDaemon2();
544513
- renderInfo2(ok2 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
544529
+ const port = parseInt(process.env["OA_PORT"] || "11435", 10);
544530
+ let switched = false;
544531
+ try {
544532
+ const resp = await fetch(`http://127.0.0.1:${port}/v1/admin/access`, {
544533
+ method: "POST",
544534
+ headers: { "Content-Type": "application/json" },
544535
+ body: JSON.stringify({ mode: val }),
544536
+ signal: AbortSignal.timeout(3e3)
544537
+ });
544538
+ switched = resp.ok;
544539
+ if (!resp.ok) {
544540
+ const txt = await resp.text().catch(() => "");
544541
+ renderWarning2(`Live access switch HTTP ${resp.status}: ${txt.slice(0, 120)}`);
544542
+ }
544543
+ } catch (e2) {
544544
+ renderWarning2(`Live access switch failed (${e2 instanceof Error ? e2.message : String(e2)}); falling back to daemon restart.`);
544545
+ }
544546
+ if (switched) {
544547
+ renderInfo2(`Access policy now '${val}' (live, no restart). Persisted to ~/.open-agents/access.`);
544548
+ } else {
544549
+ const { stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2, isDaemonRunning: isDaemonRunning2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
544550
+ stopDaemon2();
544551
+ const deadline = Date.now() + 4e3;
544552
+ while (Date.now() < deadline) {
544553
+ if (!await isDaemonRunning2(port)) break;
544554
+ await new Promise((r2) => setTimeout(r2, 200));
544555
+ }
544556
+ const ok2 = await ensureDaemon2();
544557
+ renderInfo2(ok2 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
544558
+ }
544514
544559
  return "handled";
544515
544560
  }
544516
544561
  case "host": {
@@ -576838,23 +576883,85 @@ function startApiServer(options2 = {}) {
576838
576883
  process.exit(1);
576839
576884
  }
576840
576885
  }
576841
- const accessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
576886
+ let runtimeAccessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
576887
+ try {
576888
+ const accessFile = join104(homedir38(), ".open-agents", "access");
576889
+ if (existsSync87(accessFile)) {
576890
+ const persisted = readFileSync69(accessFile, "utf8").trim();
576891
+ const resolved = resolveAccessMode(persisted, host);
576892
+ if (resolved) runtimeAccessMode = resolved;
576893
+ }
576894
+ } catch {
576895
+ }
576842
576896
  let _accessRejected = 0;
576843
576897
  const handler = (req2, res) => {
576844
576898
  const rawIp = req2.socket?.remoteAddress ?? "";
576845
- if (!isAllowedIP(rawIp, accessMode)) {
576899
+ if (!isAllowedIP(rawIp, runtimeAccessMode)) {
576846
576900
  _accessRejected++;
576847
576901
  metrics.totalErrors++;
576848
576902
  try {
576849
576903
  res.writeHead(403, { "Content-Type": "application/json" });
576850
576904
  res.end(JSON.stringify({
576851
576905
  error: "access_denied",
576852
- message: `Address ${rawIp} is not in the allowed network (mode: ${accessMode}). Set OA_ACCESS=any to disable.`
576906
+ message: `Address ${rawIp} is not in the allowed network (mode: ${runtimeAccessMode}). Set OA_ACCESS=any to disable.`
576853
576907
  }));
576854
576908
  } catch {
576855
576909
  }
576856
576910
  return;
576857
576911
  }
576912
+ try {
576913
+ const url = new URL(req2.url || "", "http://local");
576914
+ if (url.pathname === "/v1/admin/access" && req2.method === "POST") {
576915
+ if (!isLoopbackIP(rawIp)) {
576916
+ res.writeHead(403, { "Content-Type": "application/json" });
576917
+ res.end(JSON.stringify({ error: "loopback_required", message: "POST /v1/admin/access requires a loopback origin." }));
576918
+ return;
576919
+ }
576920
+ let body = "";
576921
+ req2.on("data", (chunk) => {
576922
+ body += chunk;
576923
+ if (body.length > 4096) {
576924
+ try {
576925
+ req2.destroy();
576926
+ } catch {
576927
+ }
576928
+ }
576929
+ });
576930
+ req2.on("end", () => {
576931
+ try {
576932
+ const payload = JSON.parse(body || "{}");
576933
+ const requested = (payload?.mode || "").toLowerCase().trim();
576934
+ const allowed = /* @__PURE__ */ new Set(["loopback", "lan", "any"]);
576935
+ if (!allowed.has(requested)) {
576936
+ res.writeHead(400, { "Content-Type": "application/json" });
576937
+ res.end(JSON.stringify({ error: "invalid_mode", message: `mode must be one of: ${[...allowed].join(", ")}` }));
576938
+ return;
576939
+ }
576940
+ const previous = runtimeAccessMode;
576941
+ runtimeAccessMode = requested;
576942
+ try {
576943
+ const dir = join104(homedir38(), ".open-agents");
576944
+ mkdirSync54(dir, { recursive: true });
576945
+ writeFileSync47(join104(dir, "access"), `${runtimeAccessMode}
576946
+ `, "utf8");
576947
+ } catch {
576948
+ }
576949
+ res.writeHead(200, { "Content-Type": "application/json" });
576950
+ res.end(JSON.stringify({ ok: true, previous, current: runtimeAccessMode }));
576951
+ } catch (e2) {
576952
+ res.writeHead(400, { "Content-Type": "application/json" });
576953
+ res.end(JSON.stringify({ error: "bad_request", message: e2 instanceof Error ? e2.message : String(e2) }));
576954
+ }
576955
+ });
576956
+ return;
576957
+ }
576958
+ if (url.pathname === "/v1/admin/access" && req2.method === "GET") {
576959
+ res.writeHead(200, { "Content-Type": "application/json" });
576960
+ res.end(JSON.stringify({ mode: runtimeAccessMode, host }));
576961
+ return;
576962
+ }
576963
+ } catch {
576964
+ }
576858
576965
  try {
576859
576966
  const url = new URL(req2.url || "", "http://local");
576860
576967
  if (req2.method === "POST" && url.pathname === "/v1/vision/embed") {
@@ -576971,7 +577078,7 @@ function startApiServer(options2 = {}) {
576971
577078
  const proto = useTls ? "https" : "http";
576972
577079
  log22(` Listening on ${proto}://${host}:${port}
576973
577080
  `);
576974
- log22(` Access: ${accessMode} (${describeAccessMode(accessMode)})
577081
+ log22(` Access: ${runtimeAccessMode} (${describeAccessMode(runtimeAccessMode)})
576975
577082
  `);
576976
577083
  log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
576977
577084
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.364",
3
+ "version": "0.187.365",
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",