open-agents-ai 0.103.14 → 0.103.16

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 +239 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18258,10 +18258,10 @@ ${marker}` : marker);
18258
18258
  if (!this._workingDirectory)
18259
18259
  return;
18260
18260
  try {
18261
- const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync18 } = __require("node:fs");
18261
+ const { mkdirSync: mkdirSync20, writeFileSync: writeFileSync18 } = __require("node:fs");
18262
18262
  const { join: join55 } = __require("node:path");
18263
18263
  const sessionDir = join55(this._workingDirectory, ".oa", "session", this._sessionId);
18264
- mkdirSync19(sessionDir, { recursive: true });
18264
+ mkdirSync20(sessionDir, { recursive: true });
18265
18265
  const checkpoint = {
18266
18266
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
18267
18267
  sessionId: this._sessionId,
@@ -26203,7 +26203,7 @@ import { EventEmitter as EventEmitter3 } from "node:events";
26203
26203
  import { randomBytes as randomBytes7 } from "node:crypto";
26204
26204
  import { URL as URL2 } from "node:url";
26205
26205
  import { loadavg, cpus, totalmem, freemem } from "node:os";
26206
- import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "node:fs";
26206
+ import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, mkdirSync as mkdirSync8 } from "node:fs";
26207
26207
  import { join as join35 } from "node:path";
26208
26208
  function cleanForwardHeaders(raw, targetHost) {
26209
26209
  const out = {};
@@ -26223,6 +26223,13 @@ function cleanForwardHeaders(raw, targetHost) {
26223
26223
  out.host = targetHost;
26224
26224
  return out;
26225
26225
  }
26226
+ function fmtTokens(n) {
26227
+ if (n < 1e3)
26228
+ return String(n);
26229
+ if (n < 1e6)
26230
+ return `${(n / 1e3).toFixed(1)}K`;
26231
+ return `${(n / 1e6).toFixed(1)}M`;
26232
+ }
26226
26233
  function readExposeState(stateDir) {
26227
26234
  try {
26228
26235
  const path = join35(stateDir, STATE_FILE_NAME);
@@ -26239,6 +26246,7 @@ function readExposeState(stateDir) {
26239
26246
  }
26240
26247
  function writeExposeState(stateDir, state) {
26241
26248
  try {
26249
+ mkdirSync8(stateDir, { recursive: true });
26242
26250
  writeFileSync8(join35(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
26243
26251
  } catch {
26244
26252
  }
@@ -26334,6 +26342,8 @@ var init_expose = __esm({
26334
26342
  cloudflaredProcess = null;
26335
26343
  /** PID of detached cloudflared (for killing on stop, even across OA restarts) */
26336
26344
  _cloudflaredPid = null;
26345
+ /** Periodic PID watchdog for reconnect mode (no ChildProcess close event) */
26346
+ _pidWatchdog = null;
26337
26347
  _tunnelUrl = null;
26338
26348
  _authKey;
26339
26349
  _targetUrl;
@@ -26344,7 +26354,11 @@ var init_expose = __esm({
26344
26354
  totalRequests: 0,
26345
26355
  activeConnections: 0,
26346
26356
  errors: 0,
26347
- modelUsage: /* @__PURE__ */ new Map()
26357
+ totalTokensIn: 0,
26358
+ totalTokensOut: 0,
26359
+ startedAt: Date.now(),
26360
+ modelUsage: /* @__PURE__ */ new Map(),
26361
+ users: /* @__PURE__ */ new Map()
26348
26362
  };
26349
26363
  get tunnelUrl() {
26350
26364
  return this._tunnelUrl;
@@ -26425,9 +26439,11 @@ var init_expose = __esm({
26425
26439
  });
26426
26440
  this._stats.status = "active";
26427
26441
  this.emitStats();
26442
+ this.startPidWatchdog();
26428
26443
  return this._tunnelUrl;
26429
26444
  }
26430
26445
  async stop() {
26446
+ this.stopPidWatchdog();
26431
26447
  if (this._cloudflaredPid && isProcessAlive(this._cloudflaredPid)) {
26432
26448
  try {
26433
26449
  process.kill(this._cloudflaredPid, "SIGTERM");
@@ -26476,8 +26492,10 @@ var init_expose = __esm({
26476
26492
  });
26477
26493
  try {
26478
26494
  await gateway.reconnect(state);
26495
+ options.onInfo?.(`Expose tunnel reconnected: ${state.tunnelUrl}`);
26479
26496
  return gateway;
26480
- } catch {
26497
+ } catch (err) {
26498
+ options.onError?.(`Expose reconnect failed: ${err instanceof Error ? err.message : String(err)}`);
26481
26499
  return null;
26482
26500
  }
26483
26501
  }
@@ -26502,7 +26520,20 @@ var init_expose = __esm({
26502
26520
  totalRequests: this._stats.totalRequests,
26503
26521
  activeConnections: this._stats.activeConnections,
26504
26522
  errors: this._stats.errors,
26505
- modelUsage: Object.fromEntries(this._stats.modelUsage)
26523
+ totalTokensIn: this._stats.totalTokensIn,
26524
+ totalTokensOut: this._stats.totalTokensOut,
26525
+ uptimeSeconds: Math.floor((Date.now() - this._stats.startedAt) / 1e3),
26526
+ modelUsage: Object.fromEntries(this._stats.modelUsage),
26527
+ users: Array.from(this._stats.users.values()).map((u) => ({
26528
+ ip: u.ip,
26529
+ requests: u.requests,
26530
+ tokensIn: u.tokensIn,
26531
+ tokensOut: u.tokensOut,
26532
+ activeRequests: u.activeRequests,
26533
+ firstSeen: new Date(u.firstSeen).toISOString(),
26534
+ lastSeen: new Date(u.lastSeen).toISOString(),
26535
+ models: Object.fromEntries(Array.from(u.models.entries()).map(([m, v]) => [m, { requests: v.requests, tokensIn: v.tokensIn, tokensOut: v.tokensOut }]))
26536
+ }))
26506
26537
  };
26507
26538
  res.writeHead(200, { "Content-Type": "application/json" });
26508
26539
  res.end(JSON.stringify({ ...metrics, gateway: gatewayStats }));
@@ -26512,8 +26543,26 @@ var init_expose = __esm({
26512
26543
  });
26513
26544
  return;
26514
26545
  }
26546
+ const userIp = req.headers["cf-connecting-ip"] ?? req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ?? req.socket.remoteAddress ?? "unknown";
26547
+ let user = this._stats.users.get(userIp);
26548
+ if (!user) {
26549
+ user = {
26550
+ ip: userIp,
26551
+ firstSeen: Date.now(),
26552
+ lastSeen: Date.now(),
26553
+ requests: 0,
26554
+ tokensIn: 0,
26555
+ tokensOut: 0,
26556
+ activeRequests: 0,
26557
+ models: /* @__PURE__ */ new Map()
26558
+ };
26559
+ this._stats.users.set(userIp, user);
26560
+ }
26515
26561
  this._stats.totalRequests++;
26516
26562
  this._stats.activeConnections++;
26563
+ user.requests++;
26564
+ user.activeRequests++;
26565
+ user.lastSeen = Date.now();
26517
26566
  this.emitStats();
26518
26567
  url.searchParams.delete("key");
26519
26568
  const forwardPath = url.pathname + url.search;
@@ -26522,14 +26571,22 @@ var init_expose = __esm({
26522
26571
  req.on("end", () => {
26523
26572
  const body = Buffer.concat(bodyChunks);
26524
26573
  let isStreaming = false;
26574
+ let requestModel = "";
26525
26575
  if (req.method === "POST" && body.length > 0) {
26526
26576
  try {
26527
26577
  const text = body.toString("utf8", 0, Math.min(body.length, 1024));
26528
26578
  const modelMatch = text.match(/"model"\s*:\s*"([^"]+)"/);
26529
26579
  if (modelMatch) {
26530
- const model = modelMatch[1];
26531
- const count = this._stats.modelUsage.get(model) ?? 0;
26532
- this._stats.modelUsage.set(model, count + 1);
26580
+ requestModel = modelMatch[1];
26581
+ const count = this._stats.modelUsage.get(requestModel) ?? 0;
26582
+ this._stats.modelUsage.set(requestModel, count + 1);
26583
+ let mm = user.models.get(requestModel);
26584
+ if (!mm) {
26585
+ mm = { requests: 0, tokensIn: 0, tokensOut: 0, lastUsed: Date.now() };
26586
+ user.models.set(requestModel, mm);
26587
+ }
26588
+ mm.requests++;
26589
+ mm.lastUsed = Date.now();
26533
26590
  }
26534
26591
  isStreaming = /"stream"\s*:\s*true/.test(text);
26535
26592
  } catch {
@@ -26560,6 +26617,50 @@ var init_expose = __esm({
26560
26617
  heartbeatTimer = null;
26561
26618
  }
26562
26619
  };
26620
+ let responseTail = "";
26621
+ const finalizeRequest = () => {
26622
+ user.activeRequests = Math.max(0, user.activeRequests - 1);
26623
+ this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26624
+ try {
26625
+ const promptEval = responseTail.match(/"prompt_eval_count"\s*:\s*(\d+)/);
26626
+ const evalCount = responseTail.match(/"eval_count"\s*:\s*(\d+)/);
26627
+ if (promptEval || evalCount) {
26628
+ const tIn = parseInt(promptEval?.[1] ?? "0", 10);
26629
+ const tOut = parseInt(evalCount?.[1] ?? "0", 10);
26630
+ this._stats.totalTokensIn += tIn;
26631
+ this._stats.totalTokensOut += tOut;
26632
+ user.tokensIn += tIn;
26633
+ user.tokensOut += tOut;
26634
+ if (requestModel) {
26635
+ const mm = user.models.get(requestModel);
26636
+ if (mm) {
26637
+ mm.tokensIn += tIn;
26638
+ mm.tokensOut += tOut;
26639
+ }
26640
+ }
26641
+ } else {
26642
+ const promptTokens = responseTail.match(/"prompt_tokens"\s*:\s*(\d+)/);
26643
+ const completionTokens = responseTail.match(/"completion_tokens"\s*:\s*(\d+)/);
26644
+ if (promptTokens || completionTokens) {
26645
+ const tIn = parseInt(promptTokens?.[1] ?? "0", 10);
26646
+ const tOut = parseInt(completionTokens?.[1] ?? "0", 10);
26647
+ this._stats.totalTokensIn += tIn;
26648
+ this._stats.totalTokensOut += tOut;
26649
+ user.tokensIn += tIn;
26650
+ user.tokensOut += tOut;
26651
+ if (requestModel) {
26652
+ const mm = user.models.get(requestModel);
26653
+ if (mm) {
26654
+ mm.tokensIn += tIn;
26655
+ mm.tokensOut += tOut;
26656
+ }
26657
+ }
26658
+ }
26659
+ }
26660
+ } catch {
26661
+ }
26662
+ this.emitStats();
26663
+ };
26563
26664
  const proxyReq = httpRequest({
26564
26665
  hostname: target.hostname,
26565
26666
  port: target.port || (target.protocol === "https:" ? 443 : 80),
@@ -26569,8 +26670,14 @@ var init_expose = __esm({
26569
26670
  }, (proxyRes) => {
26570
26671
  cleanupHeartbeat();
26571
26672
  proxyRes.on("error", () => {
26572
- this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26573
- this.emitStats();
26673
+ finalizeRequest();
26674
+ });
26675
+ proxyRes.on("data", (chunk) => {
26676
+ const text = chunk.toString();
26677
+ responseTail += text;
26678
+ if (responseTail.length > 2048) {
26679
+ responseTail = responseTail.slice(-2048);
26680
+ }
26574
26681
  });
26575
26682
  if (isStreaming) {
26576
26683
  if (proxyRes.statusCode !== 200) {
@@ -26590,8 +26697,7 @@ var init_expose = __esm({
26590
26697
  } catch {
26591
26698
  }
26592
26699
  this._stats.errors++;
26593
- this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26594
- this.emitStats();
26700
+ finalizeRequest();
26595
26701
  });
26596
26702
  return;
26597
26703
  }
@@ -26601,14 +26707,12 @@ var init_expose = __esm({
26601
26707
  proxyRes.pipe(res);
26602
26708
  }
26603
26709
  proxyRes.on("end", () => {
26604
- this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26605
- this.emitStats();
26710
+ finalizeRequest();
26606
26711
  });
26607
26712
  });
26608
26713
  proxyReq.on("error", (err) => {
26609
26714
  cleanupHeartbeat();
26610
26715
  this._stats.errors++;
26611
- this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26612
26716
  if (!res.headersSent) {
26613
26717
  res.writeHead(502, { "Content-Type": "application/json" });
26614
26718
  res.end(JSON.stringify({ error: `Backend unreachable: ${err.message}` }));
@@ -26624,7 +26728,7 @@ var init_expose = __esm({
26624
26728
  } catch {
26625
26729
  }
26626
26730
  }
26627
- this.emitStats();
26731
+ finalizeRequest();
26628
26732
  });
26629
26733
  if (body.length > 0) {
26630
26734
  proxyReq.write(body);
@@ -26632,6 +26736,7 @@ var init_expose = __esm({
26632
26736
  proxyReq.end();
26633
26737
  });
26634
26738
  req.on("error", () => {
26739
+ user.activeRequests = Math.max(0, user.activeRequests - 1);
26635
26740
  this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26636
26741
  this.emitStats();
26637
26742
  });
@@ -26662,8 +26767,12 @@ var init_expose = __esm({
26662
26767
  });
26663
26768
  this._cloudflaredPid = this.cloudflaredProcess.pid ?? null;
26664
26769
  let urlFound = false;
26770
+ let stderrOutput = "";
26665
26771
  const handleOutput = (data) => {
26666
26772
  const text = data.toString();
26773
+ stderrOutput += text;
26774
+ if (stderrOutput.length > 4096)
26775
+ stderrOutput = stderrOutput.slice(-4096);
26667
26776
  const urlMatch = text.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
26668
26777
  if (urlMatch && !urlFound) {
26669
26778
  urlFound = true;
@@ -26683,7 +26792,8 @@ var init_expose = __esm({
26683
26792
  this.cloudflaredProcess.on("close", (code) => {
26684
26793
  if (!urlFound) {
26685
26794
  clearTimeout(timeout);
26686
- reject(new Error(`Cloudflared exited with code ${code} before providing URL`));
26795
+ const hint = stderrOutput.trim().split("\n").slice(-3).join(" | ");
26796
+ reject(new Error(`Cloudflared exited with code ${code}. ${hint ? "Output: " + hint : ""}`));
26687
26797
  }
26688
26798
  if (this._stats.status === "active") {
26689
26799
  this.options.onInfo?.("Cloudflared tunnel died \u2014 restarting...");
@@ -26702,7 +26812,8 @@ var init_expose = __esm({
26702
26812
  this._tunnelUrl = await this.startCloudflared(this._proxyPort);
26703
26813
  this._stats.status = "active";
26704
26814
  this.emitStats();
26705
- this.options.onInfo?.(`Tunnel restarted: ${this._tunnelUrl}`);
26815
+ this.options.onInfo?.(`Tunnel restarted with new URL \u2014 share with consumers:
26816
+ ${this.formatConnectionInfo()}`);
26706
26817
  if (this._stateDir) {
26707
26818
  writeExposeState(this._stateDir, {
26708
26819
  pid: this._cloudflaredPid,
@@ -26718,6 +26829,32 @@ var init_expose = __esm({
26718
26829
  this.options.onError?.(`Tunnel restart failed: ${err instanceof Error ? err.message : String(err)}`);
26719
26830
  }
26720
26831
  }
26832
+ /**
26833
+ * Periodically check if the cloudflared PID is still alive.
26834
+ * Used in reconnect mode where we don't have a ChildProcess close event.
26835
+ * If cloudflared dies, triggers auto-restart.
26836
+ */
26837
+ startPidWatchdog() {
26838
+ this.stopPidWatchdog();
26839
+ this._pidWatchdog = setInterval(() => {
26840
+ if (!this._cloudflaredPid || !isProcessAlive(this._cloudflaredPid)) {
26841
+ this.stopPidWatchdog();
26842
+ if (this._stats.status === "active") {
26843
+ this.options.onInfo?.("Cloudflared tunnel died (detected by watchdog) \u2014 restarting...");
26844
+ this._stats.status = "error";
26845
+ this.emitStats();
26846
+ this.restartCloudflared();
26847
+ }
26848
+ }
26849
+ }, 1e4);
26850
+ this._pidWatchdog.unref();
26851
+ }
26852
+ stopPidWatchdog() {
26853
+ if (this._pidWatchdog) {
26854
+ clearInterval(this._pidWatchdog);
26855
+ this._pidWatchdog = null;
26856
+ }
26857
+ }
26721
26858
  // ── Helpers ─────────────────────────────────────────────────────────────
26722
26859
  findFreePort() {
26723
26860
  return new Promise((resolve31, reject) => {
@@ -26735,7 +26872,11 @@ var init_expose = __esm({
26735
26872
  });
26736
26873
  }
26737
26874
  emitStats() {
26738
- this.emit("stats", { ...this._stats, modelUsage: new Map(this._stats.modelUsage) });
26875
+ this.emit("stats", {
26876
+ ...this._stats,
26877
+ modelUsage: new Map(this._stats.modelUsage),
26878
+ users: new Map(this._stats.users)
26879
+ });
26739
26880
  }
26740
26881
  /** Format connection info for display */
26741
26882
  formatConnectionInfo() {
@@ -26761,15 +26902,50 @@ var init_expose = __esm({
26761
26902
  formatStats() {
26762
26903
  const s = this._stats;
26763
26904
  const lines = [];
26905
+ const uptimeSec = Math.floor((Date.now() - s.startedAt) / 1e3);
26906
+ const uptimeStr = uptimeSec < 60 ? `${uptimeSec}s` : uptimeSec < 3600 ? `${Math.floor(uptimeSec / 60)}m ${uptimeSec % 60}s` : `${Math.floor(uptimeSec / 3600)}h ${Math.floor(uptimeSec % 3600 / 60)}m`;
26764
26907
  lines.push(` ${c2.bold("Expose Gateway Stats")}`);
26765
- lines.push(` ${c2.cyan("Status".padEnd(16))} ${s.status === "active" ? c2.green("active") : s.status === "error" ? c2.red("error") : c2.yellow("standby")}`);
26766
- lines.push(` ${c2.cyan("Total requests".padEnd(16))} ${s.totalRequests}`);
26767
- lines.push(` ${c2.cyan("Active conns".padEnd(16))} ${s.activeConnections}`);
26768
- lines.push(` ${c2.cyan("Errors".padEnd(16))} ${s.errors}`);
26908
+ lines.push(` ${c2.cyan("Status".padEnd(18))} ${s.status === "active" ? c2.green("active") : s.status === "error" ? c2.red("error") : c2.yellow("standby")}`);
26909
+ lines.push(` ${c2.cyan("Uptime".padEnd(18))} ${uptimeStr}`);
26910
+ lines.push(` ${c2.cyan("Total requests".padEnd(18))} ${s.totalRequests}`);
26911
+ lines.push(` ${c2.cyan("Active conns".padEnd(18))} ${s.activeConnections}`);
26912
+ lines.push(` ${c2.cyan("Errors".padEnd(18))} ${s.errors}`);
26913
+ lines.push(` ${c2.cyan("Tokens in".padEnd(18))} ${fmtTokens(s.totalTokensIn)}`);
26914
+ lines.push(` ${c2.cyan("Tokens out".padEnd(18))} ${fmtTokens(s.totalTokensOut)}`);
26769
26915
  if (s.modelUsage.size > 0) {
26770
- lines.push(` ${c2.cyan("Models used:")}`);
26916
+ lines.push("");
26917
+ lines.push(` ${c2.bold("Models")}`);
26771
26918
  for (const [model, count] of s.modelUsage) {
26772
- lines.push(` ${model}: ${count} requests`);
26919
+ let mIn = 0, mOut = 0;
26920
+ for (const user of s.users.values()) {
26921
+ const mm = user.models.get(model);
26922
+ if (mm) {
26923
+ mIn += mm.tokensIn;
26924
+ mOut += mm.tokensOut;
26925
+ }
26926
+ }
26927
+ lines.push(` ${c2.cyan(model.padEnd(30))} ${count} reqs ${c2.dim(`in:${fmtTokens(mIn)} out:${fmtTokens(mOut)}`)}`);
26928
+ }
26929
+ }
26930
+ if (s.users.size > 0) {
26931
+ lines.push("");
26932
+ lines.push(` ${c2.bold("Active Users")} (${s.users.size})`);
26933
+ for (const user of s.users.values()) {
26934
+ const ageSec = Math.floor((Date.now() - user.firstSeen) / 1e3);
26935
+ const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h ${Math.floor(ageSec % 3600 / 60)}m`;
26936
+ const lastSec = Math.floor((Date.now() - user.lastSeen) / 1e3);
26937
+ const lastStr = lastSec < 5 ? "now" : lastSec < 60 ? `${lastSec}s ago` : `${Math.floor(lastSec / 60)}m ago`;
26938
+ const activeTag = user.activeRequests > 0 ? c2.green(` [${user.activeRequests} active]`) : "";
26939
+ lines.push(` ${c2.bold(user.ip)}${activeTag}`);
26940
+ lines.push(` ${c2.dim("Session:")} ${ageStr} ${c2.dim("Last seen:")} ${lastStr} ${c2.dim("Requests:")} ${user.requests}`);
26941
+ lines.push(` ${c2.dim("Tokens:")} in:${fmtTokens(user.tokensIn)} out:${fmtTokens(user.tokensOut)} ${c2.dim("Total:")} ${fmtTokens(user.tokensIn + user.tokensOut)}`);
26942
+ if (user.models.size > 0) {
26943
+ const modelParts = [];
26944
+ for (const [m, mm] of user.models) {
26945
+ modelParts.push(`${m} (${mm.requests} reqs, ${fmtTokens(mm.tokensIn + mm.tokensOut)} tokens)`);
26946
+ }
26947
+ lines.push(` ${c2.dim("Models:")} ${modelParts.join(", ")}`);
26948
+ }
26773
26949
  }
26774
26950
  }
26775
26951
  return lines.join("\n");
@@ -26792,7 +26968,7 @@ var init_types = __esm({
26792
26968
 
26793
26969
  // packages/cli/dist/tui/p2p/secret-vault.js
26794
26970
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
26795
- import { readFileSync as readFileSync19, writeFileSync as writeFileSync9, existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
26971
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync9, existsSync as existsSync27, mkdirSync as mkdirSync9 } from "node:fs";
26796
26972
  import { join as join36, dirname as dirname13 } from "node:path";
26797
26973
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
26798
26974
  var init_secret_vault = __esm({
@@ -27006,7 +27182,7 @@ var init_secret_vault = __esm({
27006
27182
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
27007
27183
  const dir = dirname13(this.storePath);
27008
27184
  if (!existsSync27(dir))
27009
- mkdirSync8(dir, { recursive: true });
27185
+ mkdirSync9(dir, { recursive: true });
27010
27186
  writeFileSync9(this.storePath, blob, { mode: 384 });
27011
27187
  }
27012
27188
  /**
@@ -28388,13 +28564,13 @@ var init_dist6 = __esm({
28388
28564
  });
28389
28565
 
28390
28566
  // packages/cli/dist/tui/oa-directory.js
28391
- import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync4 } from "node:fs";
28567
+ import { existsSync as existsSync29, mkdirSync as mkdirSync10, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync4 } from "node:fs";
28392
28568
  import { join as join39, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
28393
28569
  import { homedir as homedir9 } from "node:os";
28394
28570
  function initOaDirectory(repoRoot) {
28395
28571
  const oaPath = join39(repoRoot, OA_DIR);
28396
28572
  for (const sub of SUBDIRS) {
28397
- mkdirSync9(join39(oaPath, sub), { recursive: true });
28573
+ mkdirSync10(join39(oaPath, sub), { recursive: true });
28398
28574
  }
28399
28575
  try {
28400
28576
  const gitignorePath = join39(repoRoot, ".gitignore");
@@ -28424,7 +28600,7 @@ function loadProjectSettings(repoRoot) {
28424
28600
  }
28425
28601
  function saveProjectSettings(repoRoot, settings) {
28426
28602
  const oaPath = join39(repoRoot, OA_DIR);
28427
- mkdirSync9(oaPath, { recursive: true });
28603
+ mkdirSync10(oaPath, { recursive: true });
28428
28604
  const existing = loadProjectSettings(repoRoot);
28429
28605
  const merged = { ...existing, ...settings };
28430
28606
  writeFileSync10(join39(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
@@ -28441,7 +28617,7 @@ function loadGlobalSettings() {
28441
28617
  }
28442
28618
  function saveGlobalSettings(settings) {
28443
28619
  const dir = join39(homedir9(), ".open-agents");
28444
- mkdirSync9(dir, { recursive: true });
28620
+ mkdirSync10(dir, { recursive: true });
28445
28621
  const existing = loadGlobalSettings();
28446
28622
  const merged = { ...existing, ...settings };
28447
28623
  writeFileSync10(join39(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
@@ -28566,13 +28742,13 @@ ${tree}\`\`\`
28566
28742
  }
28567
28743
  const content = sections.join("\n");
28568
28744
  const contextDir = join39(repoRoot, OA_DIR, "context");
28569
- mkdirSync9(contextDir, { recursive: true });
28745
+ mkdirSync10(contextDir, { recursive: true });
28570
28746
  writeFileSync10(join39(contextDir, "project-map.md"), content, "utf-8");
28571
28747
  return content;
28572
28748
  }
28573
28749
  function saveSession(repoRoot, session) {
28574
28750
  const historyDir = join39(repoRoot, OA_DIR, "history");
28575
- mkdirSync9(historyDir, { recursive: true });
28751
+ mkdirSync10(historyDir, { recursive: true });
28576
28752
  writeFileSync10(join39(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
28577
28753
  }
28578
28754
  function loadRecentSessions(repoRoot, limit = 5) {
@@ -28597,7 +28773,7 @@ function loadRecentSessions(repoRoot, limit = 5) {
28597
28773
  }
28598
28774
  function savePendingTask(repoRoot, task) {
28599
28775
  const historyDir = join39(repoRoot, OA_DIR, "history");
28600
- mkdirSync9(historyDir, { recursive: true });
28776
+ mkdirSync10(historyDir, { recursive: true });
28601
28777
  writeFileSync10(join39(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
28602
28778
  }
28603
28779
  function loadPendingTask(repoRoot) {
@@ -28617,7 +28793,7 @@ function loadPendingTask(repoRoot) {
28617
28793
  }
28618
28794
  function saveSessionContext(repoRoot, entry) {
28619
28795
  const contextDir = join39(repoRoot, OA_DIR, "context");
28620
- mkdirSync9(contextDir, { recursive: true });
28796
+ mkdirSync10(contextDir, { recursive: true });
28621
28797
  const filePath = join39(contextDir, CONTEXT_SAVE_FILE);
28622
28798
  let ctx;
28623
28799
  try {
@@ -28774,7 +28950,7 @@ function loadUsageFile(filePath) {
28774
28950
  }
28775
28951
  function saveUsageFile(filePath, data) {
28776
28952
  const dir = join39(filePath, "..");
28777
- mkdirSync9(dir, { recursive: true });
28953
+ mkdirSync10(dir, { recursive: true });
28778
28954
  writeFileSync10(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28779
28955
  }
28780
28956
  function recordUsage(kind, value, opts) {
@@ -28880,7 +29056,7 @@ var init_oa_directory = __esm({
28880
29056
  import * as readline from "node:readline";
28881
29057
  import { execSync as execSync25, spawn as spawn15, exec as exec2 } from "node:child_process";
28882
29058
  import { promisify as promisify5 } from "node:util";
28883
- import { existsSync as existsSync30, writeFileSync as writeFileSync11, mkdirSync as mkdirSync10 } from "node:fs";
29059
+ import { existsSync as existsSync30, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11 } from "node:fs";
28884
29060
  import { join as join40 } from "node:path";
28885
29061
  import { homedir as homedir10, platform } from "node:os";
28886
29062
  function detectSystemSpecs() {
@@ -29913,7 +30089,7 @@ async function doSetup(config, rl) {
29913
30089
  `PARAMETER stop "<|endoftext|>"`
29914
30090
  ].join("\n");
29915
30091
  const modelDir2 = join40(homedir10(), ".open-agents", "models");
29916
- mkdirSync10(modelDir2, { recursive: true });
30092
+ mkdirSync11(modelDir2, { recursive: true });
29917
30093
  const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
29918
30094
  writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
29919
30095
  process.stdout.write(` ${c2.dim("Creating model...")} `);
@@ -30022,7 +30198,7 @@ function ensureVenv(log) {
30022
30198
  return null;
30023
30199
  }
30024
30200
  try {
30025
- mkdirSync10(join40(homedir10(), ".open-agents"), { recursive: true });
30201
+ mkdirSync11(join40(homedir10(), ".open-agents"), { recursive: true });
30026
30202
  execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
30027
30203
  execSync25(`"${join40(venvDir, "bin", "pip")}" install --upgrade pip`, {
30028
30204
  stdio: "pipe",
@@ -30355,7 +30531,7 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB) {
30355
30531
  `PARAMETER stop "<|endoftext|>"`
30356
30532
  ].join("\n");
30357
30533
  const modelDir2 = join40(homedir10(), ".open-agents", "models");
30358
- mkdirSync10(modelDir2, { recursive: true });
30534
+ mkdirSync11(modelDir2, { recursive: true });
30359
30535
  const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
30360
30536
  writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
30361
30537
  await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
@@ -33712,7 +33888,7 @@ var init_carousel = __esm({
33712
33888
  });
33713
33889
 
33714
33890
  // packages/cli/dist/tui/carousel-descriptors.js
33715
- import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
33891
+ import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, readdirSync as readdirSync9 } from "node:fs";
33716
33892
  import { join as join42, basename as basename11 } from "node:path";
33717
33893
  function loadToolProfile(repoRoot) {
33718
33894
  const filePath = join42(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
@@ -33726,7 +33902,7 @@ function loadToolProfile(repoRoot) {
33726
33902
  }
33727
33903
  function saveToolProfile(repoRoot, profile) {
33728
33904
  const contextDir = join42(repoRoot, OA_DIR, "context");
33729
- mkdirSync11(contextDir, { recursive: true });
33905
+ mkdirSync12(contextDir, { recursive: true });
33730
33906
  writeFileSync12(join42(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
33731
33907
  }
33732
33908
  function categorizeToolCall(toolName) {
@@ -33797,7 +33973,7 @@ function loadCachedDescriptors(repoRoot) {
33797
33973
  }
33798
33974
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
33799
33975
  const contextDir = join42(repoRoot, OA_DIR, "context");
33800
- mkdirSync11(contextDir, { recursive: true });
33976
+ mkdirSync12(contextDir, { recursive: true });
33801
33977
  const cached = {
33802
33978
  phrases,
33803
33979
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -34065,7 +34241,7 @@ var init_carousel_descriptors = __esm({
34065
34241
  });
34066
34242
 
34067
34243
  // packages/cli/dist/tui/voice.js
34068
- import { existsSync as existsSync33, mkdirSync as mkdirSync12, writeFileSync as writeFileSync13, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
34244
+ import { existsSync as existsSync33, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
34069
34245
  import { join as join43 } from "node:path";
34070
34246
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
34071
34247
  import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
@@ -35336,7 +35512,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35336
35512
  if (this.ort)
35337
35513
  return;
35338
35514
  const arch = process.arch;
35339
- mkdirSync12(voiceDir(), { recursive: true });
35515
+ mkdirSync13(voiceDir(), { recursive: true });
35340
35516
  const pkgPath = join43(voiceDir(), "package.json");
35341
35517
  const expectedDeps = {
35342
35518
  "onnxruntime-node": "^1.21.0",
@@ -35430,7 +35606,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
35430
35606
  const configPath = modelConfigPath(id);
35431
35607
  if (existsSync33(onnxPath) && existsSync33(configPath))
35432
35608
  return;
35433
- mkdirSync12(dir, { recursive: true });
35609
+ mkdirSync13(dir, { recursive: true });
35434
35610
  if (!existsSync33(configPath)) {
35435
35611
  renderInfo(`Downloading ${model.label} voice config...`);
35436
35612
  const configResp = await fetch(model.configUrl);
@@ -36340,13 +36516,13 @@ var init_stream_renderer = __esm({
36340
36516
  });
36341
36517
 
36342
36518
  // packages/cli/dist/tui/edit-history.js
36343
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync13 } from "node:fs";
36519
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync14 } from "node:fs";
36344
36520
  import { join as join44 } from "node:path";
36345
36521
  function createEditHistoryLogger(repoRoot, sessionId) {
36346
36522
  const historyDir = join44(repoRoot, ".oa", "history");
36347
36523
  const logPath = join44(historyDir, "edits.jsonl");
36348
36524
  try {
36349
- mkdirSync13(historyDir, { recursive: true });
36525
+ mkdirSync14(historyDir, { recursive: true });
36350
36526
  } catch {
36351
36527
  }
36352
36528
  function logToolCall(toolName, toolArgs, success) {
@@ -36486,7 +36662,7 @@ var init_promptLoader3 = __esm({
36486
36662
  });
36487
36663
 
36488
36664
  // packages/cli/dist/tui/dream-engine.js
36489
- import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
36665
+ import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
36490
36666
  import { join as join46, basename as basename12 } from "node:path";
36491
36667
  import { execSync as execSync28 } from "node:child_process";
36492
36668
  function loadAutoresearchMemory(repoRoot) {
@@ -36690,7 +36866,7 @@ var init_dream_engine = __esm({
36690
36866
  }
36691
36867
  try {
36692
36868
  const dir = join46(targetPath, "..");
36693
- mkdirSync14(dir, { recursive: true });
36869
+ mkdirSync15(dir, { recursive: true });
36694
36870
  writeFileSync14(targetPath, content, "utf-8");
36695
36871
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
36696
36872
  } catch (err) {
@@ -36779,7 +36955,7 @@ var init_dream_engine = __esm({
36779
36955
  }
36780
36956
  try {
36781
36957
  const dir = join46(targetPath, "..");
36782
- mkdirSync14(dir, { recursive: true });
36958
+ mkdirSync15(dir, { recursive: true });
36783
36959
  writeFileSync14(targetPath, content, "utf-8");
36784
36960
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
36785
36961
  } catch (err) {
@@ -36906,7 +37082,7 @@ var init_dream_engine = __esm({
36906
37082
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
36907
37083
  results: []
36908
37084
  };
36909
- mkdirSync14(this.dreamsDir, { recursive: true });
37085
+ mkdirSync15(this.dreamsDir, { recursive: true });
36910
37086
  this.saveDreamState();
36911
37087
  try {
36912
37088
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -37558,7 +37734,7 @@ ${summaryResult}
37558
37734
  *Generated by open-agents autoresearch swarm*
37559
37735
  `;
37560
37736
  try {
37561
- mkdirSync14(this.dreamsDir, { recursive: true });
37737
+ mkdirSync15(this.dreamsDir, { recursive: true });
37562
37738
  writeFileSync14(reportPath, report, "utf-8");
37563
37739
  } catch {
37564
37740
  }
@@ -37627,7 +37803,7 @@ ${summaryResult}
37627
37803
  saveVersionCheckpoint(cycle) {
37628
37804
  const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
37629
37805
  try {
37630
- mkdirSync14(checkpointDir, { recursive: true });
37806
+ mkdirSync15(checkpointDir, { recursive: true });
37631
37807
  try {
37632
37808
  const gitStatus = execSync28("git status --porcelain", {
37633
37809
  cwd: this.repoRoot,
@@ -38094,7 +38270,7 @@ var init_bless_engine = __esm({
38094
38270
  });
38095
38271
 
38096
38272
  // packages/cli/dist/tui/dmn-engine.js
38097
- import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync6 } from "node:fs";
38273
+ import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, readdirSync as readdirSync11, unlinkSync as unlinkSync6 } from "node:fs";
38098
38274
  import { join as join47, basename as basename13 } from "node:path";
38099
38275
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
38100
38276
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
@@ -38210,7 +38386,7 @@ var init_dmn_engine = __esm({
38210
38386
  this.repoRoot = repoRoot;
38211
38387
  this.stateDir = join47(repoRoot, ".oa", "dmn");
38212
38388
  this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
38213
- mkdirSync15(this.historyDir, { recursive: true });
38389
+ mkdirSync16(this.historyDir, { recursive: true });
38214
38390
  this.loadState();
38215
38391
  }
38216
38392
  get stats() {
@@ -39675,7 +39851,7 @@ var init_tool_policy = __esm({
39675
39851
  });
39676
39852
 
39677
39853
  // packages/cli/dist/tui/telegram-bridge.js
39678
- import { mkdirSync as mkdirSync16, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
39854
+ import { mkdirSync as mkdirSync17, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
39679
39855
  import { join as join49, resolve as resolve27 } from "node:path";
39680
39856
  import { writeFile as writeFileAsync } from "node:fs/promises";
39681
39857
  function convertMarkdownToTelegramHTML(md) {
@@ -40004,7 +40180,7 @@ with summary "no_reply" to silently skip without responding.
40004
40180
  this.polling = true;
40005
40181
  this.abortController = new AbortController();
40006
40182
  try {
40007
- mkdirSync16(this.mediaCacheDir, { recursive: true });
40183
+ mkdirSync17(this.mediaCacheDir, { recursive: true });
40008
40184
  } catch {
40009
40185
  }
40010
40186
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -42277,7 +42453,7 @@ import { cwd } from "node:process";
42277
42453
  import { resolve as resolve28, join as join50, dirname as dirname17, extname as extname9 } from "node:path";
42278
42454
  import { createRequire as createRequire2 } from "node:module";
42279
42455
  import { fileURLToPath as fileURLToPath12 } from "node:url";
42280
- import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
42456
+ import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync18 } from "node:fs";
42281
42457
  import { existsSync as existsSync39 } from "node:fs";
42282
42458
  import { homedir as homedir13 } from "node:os";
42283
42459
  function formatTimeAgo(date) {
@@ -43479,7 +43655,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
43479
43655
  if (!line.trim())
43480
43656
  return;
43481
43657
  try {
43482
- mkdirSync17(HISTORY_DIR, { recursive: true });
43658
+ mkdirSync18(HISTORY_DIR, { recursive: true });
43483
43659
  appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
43484
43660
  if (Math.random() < 0.02) {
43485
43661
  const all = readFileSync29(HISTORY_FILE, "utf8").trim().split("\n");
@@ -46114,7 +46290,7 @@ __export(eval_exports, {
46114
46290
  evalCommand: () => evalCommand
46115
46291
  });
46116
46292
  import { tmpdir as tmpdir7 } from "node:os";
46117
- import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync17 } from "node:fs";
46293
+ import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync17 } from "node:fs";
46118
46294
  import { join as join53 } from "node:path";
46119
46295
  async function evalCommand(opts, config) {
46120
46296
  const suiteName = opts.suite ?? "basic";
@@ -46241,7 +46417,7 @@ async function evalCommand(opts, config) {
46241
46417
  }
46242
46418
  function createTempEvalRepo() {
46243
46419
  const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
46244
- mkdirSync18(dir, { recursive: true });
46420
+ mkdirSync19(dir, { recursive: true });
46245
46421
  writeFileSync17(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
46246
46422
  return dir;
46247
46423
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.14",
3
+ "version": "0.103.16",
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",