open-agents-ai 0.79.0 → 0.80.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.
Files changed (2) hide show
  1. package/dist/index.js +98 -51
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11203,10 +11203,11 @@ ${truncated}`, durationMs: performance.now() - start };
11203
11203
 
11204
11204
  // packages/execution/dist/tools/nexus.js
11205
11205
  import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3 } from "node:fs/promises";
11206
- import { existsSync as existsSync21 } from "node:fs";
11206
+ import { existsSync as existsSync21, readFileSync as readFileSync15 } from "node:fs";
11207
11207
  import { resolve as resolve26, join as join28 } from "node:path";
11208
11208
  import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
11209
11209
  import { execSync as execSync21, spawn as spawn10 } from "node:child_process";
11210
+ import { hostname, userInfo } from "node:os";
11210
11211
  function containsKeyMaterial(input) {
11211
11212
  for (const pattern of KEY_PATTERNS) {
11212
11213
  if (pattern.test(input))
@@ -11396,6 +11397,17 @@ setInterval(() => {
11396
11397
  } catch {}
11397
11398
  }, 500);
11398
11399
 
11400
+ // Crash protection \u2014 prevent unhandled errors from killing the daemon
11401
+ process.on('uncaughtException', (err) => {
11402
+ console.error('Nexus daemon uncaughtException:', err.message || err);
11403
+ writeStatus({ error: 'uncaughtException: ' + (err.message || String(err)) });
11404
+ });
11405
+ process.on('unhandledRejection', (reason) => {
11406
+ const msg = reason instanceof Error ? reason.message : String(reason);
11407
+ console.error('Nexus daemon unhandledRejection:', msg);
11408
+ // Do NOT exit \u2014 keep daemon alive
11409
+ });
11410
+
11399
11411
  // Connect
11400
11412
  (async () => {
11401
11413
  try {
@@ -11418,7 +11430,7 @@ setInterval(() => {
11418
11430
  // Graceful shutdown
11419
11431
  process.on('SIGTERM', async () => {
11420
11432
  for (const [, room] of rooms) { try { await room.leave(); } catch {} }
11421
- await nexus.disconnect();
11433
+ try { await nexus.disconnect(); } catch {}
11422
11434
  try { unlinkSync(pidFile); } catch {}
11423
11435
  try { unlinkSync(statusFile); } catch {}
11424
11436
  process.exit(0);
@@ -11592,7 +11604,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
11592
11604
  if (!existsSync21(pidFile))
11593
11605
  return null;
11594
11606
  try {
11595
- const pid = parseInt(__require("node:fs").readFileSync(pidFile, "utf8").trim(), 10);
11607
+ const pid = parseInt(readFileSync15(pidFile, "utf8").trim(), 10);
11596
11608
  process.kill(pid, 0);
11597
11609
  return pid;
11598
11610
  } catch {
@@ -11635,11 +11647,23 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
11635
11647
  if (existsSync21(statusFile2)) {
11636
11648
  try {
11637
11649
  const status = JSON.parse(await readFile13(statusFile2, "utf8"));
11638
- return `Already connected (pid: ${existingPid}, peerId: ${status.peerId || "starting..."})`;
11650
+ if (status.connected && status.peerId) {
11651
+ return `Already connected (pid: ${existingPid}, peerId: ${status.peerId})`;
11652
+ }
11639
11653
  } catch {
11640
11654
  }
11641
11655
  }
11642
- return `Daemon already running (pid: ${existingPid}).`;
11656
+ try {
11657
+ process.kill(existingPid, "SIGTERM");
11658
+ } catch {
11659
+ }
11660
+ await new Promise((r) => setTimeout(r, 500));
11661
+ }
11662
+ for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
11663
+ const p = join28(this.nexusDir, f);
11664
+ if (existsSync21(p))
11665
+ await unlink(p).catch(() => {
11666
+ });
11643
11667
  }
11644
11668
  const nodeModulesDir = resolve26(this.repoRoot, "node_modules");
11645
11669
  let nexusResolved = false;
@@ -11907,7 +11931,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
11907
11931
  const privKey = randomBytes6(32);
11908
11932
  const address = "0x" + createHash("sha256").update(privKey).digest("hex").slice(0, 40);
11909
11933
  const salt = randomBytes6(32);
11910
- const key = scryptSync(`${__require("node:os").hostname()}:${__require("node:os").userInfo().username}:nexus-wallet`, salt, 32, { N: 16384, r: 8, p: 1 });
11934
+ const key = scryptSync(`${hostname()}:${userInfo().username}:nexus-wallet`, salt, 32, { N: 16384, r: 8, p: 1 });
11911
11935
  const iv = randomBytes6(16);
11912
11936
  const cipher = createCipheriv("aes-256-gcm", key, iv);
11913
11937
  let enc = cipher.update(privKey.toString("hex"), "utf8", "hex");
@@ -12788,7 +12812,7 @@ var init_dist3 = __esm({
12788
12812
  });
12789
12813
 
12790
12814
  // packages/orchestrator/dist/promptLoader.js
12791
- import { readFileSync as readFileSync15, existsSync as existsSync22 } from "node:fs";
12815
+ import { readFileSync as readFileSync16, existsSync as existsSync22 } from "node:fs";
12792
12816
  import { join as join29, dirname as dirname10 } from "node:path";
12793
12817
  import { fileURLToPath as fileURLToPath7 } from "node:url";
12794
12818
  function loadPrompt(promptPath, vars) {
@@ -12798,7 +12822,7 @@ function loadPrompt(promptPath, vars) {
12798
12822
  if (!existsSync22(fullPath)) {
12799
12823
  throw new Error(`Prompt file not found: ${fullPath}`);
12800
12824
  }
12801
- content = readFileSync15(fullPath, "utf-8");
12825
+ content = readFileSync16(fullPath, "utf-8");
12802
12826
  cache.set(promptPath, content);
12803
12827
  }
12804
12828
  if (!vars)
@@ -23617,7 +23641,7 @@ var init_types = __esm({
23617
23641
 
23618
23642
  // packages/cli/dist/tui/p2p/secret-vault.js
23619
23643
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
23620
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync7, existsSync as existsSync24, mkdirSync as mkdirSync7 } from "node:fs";
23644
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync24, mkdirSync as mkdirSync7 } from "node:fs";
23621
23645
  import { join as join33, dirname as dirname12 } from "node:path";
23622
23646
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
23623
23647
  var init_secret_vault = __esm({
@@ -23841,7 +23865,7 @@ var init_secret_vault = __esm({
23841
23865
  load(passphrase) {
23842
23866
  if (!this.storePath || !existsSync24(this.storePath))
23843
23867
  return 0;
23844
- const blob = readFileSync16(this.storePath);
23868
+ const blob = readFileSync17(this.storePath);
23845
23869
  if (blob.length < SALT_LEN + IV_LEN + 16) {
23846
23870
  throw new Error("Vault file is corrupted (too small)");
23847
23871
  }
@@ -25052,7 +25076,7 @@ var init_render2 = __esm({
25052
25076
  });
25053
25077
 
25054
25078
  // packages/prompts/dist/promptLoader.js
25055
- import { readFileSync as readFileSync17, existsSync as existsSync25 } from "node:fs";
25079
+ import { readFileSync as readFileSync18, existsSync as existsSync25 } from "node:fs";
25056
25080
  import { join as join34, dirname as dirname13 } from "node:path";
25057
25081
  import { fileURLToPath as fileURLToPath9 } from "node:url";
25058
25082
  function loadPrompt2(promptPath, vars) {
@@ -25062,7 +25086,7 @@ function loadPrompt2(promptPath, vars) {
25062
25086
  if (!existsSync25(fullPath)) {
25063
25087
  throw new Error(`Prompt file not found: ${fullPath}`);
25064
25088
  }
25065
- content = readFileSync17(fullPath, "utf-8");
25089
+ content = readFileSync18(fullPath, "utf-8");
25066
25090
  cache2.set(promptPath, content);
25067
25091
  }
25068
25092
  if (!vars)
@@ -25204,7 +25228,7 @@ var init_dist6 = __esm({
25204
25228
  });
25205
25229
 
25206
25230
  // packages/cli/dist/tui/oa-directory.js
25207
- import { existsSync as existsSync26, mkdirSync as mkdirSync8, readFileSync as readFileSync18, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
25231
+ import { existsSync as existsSync26, mkdirSync as mkdirSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
25208
25232
  import { join as join36, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
25209
25233
  import { homedir as homedir9 } from "node:os";
25210
25234
  function initOaDirectory(repoRoot) {
@@ -25216,7 +25240,7 @@ function initOaDirectory(repoRoot) {
25216
25240
  const gitignorePath = join36(repoRoot, ".gitignore");
25217
25241
  const settingsPattern = ".oa/settings.json";
25218
25242
  if (existsSync26(gitignorePath)) {
25219
- const content = readFileSync18(gitignorePath, "utf-8");
25243
+ const content = readFileSync19(gitignorePath, "utf-8");
25220
25244
  if (!content.includes(settingsPattern)) {
25221
25245
  writeFileSync8(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
25222
25246
  }
@@ -25232,7 +25256,7 @@ function loadProjectSettings(repoRoot) {
25232
25256
  const settingsPath = join36(repoRoot, OA_DIR, "settings.json");
25233
25257
  try {
25234
25258
  if (existsSync26(settingsPath)) {
25235
- return JSON.parse(readFileSync18(settingsPath, "utf-8"));
25259
+ return JSON.parse(readFileSync19(settingsPath, "utf-8"));
25236
25260
  }
25237
25261
  } catch {
25238
25262
  }
@@ -25249,7 +25273,7 @@ function loadGlobalSettings() {
25249
25273
  const settingsPath = join36(homedir9(), ".open-agents", "settings.json");
25250
25274
  try {
25251
25275
  if (existsSync26(settingsPath)) {
25252
- return JSON.parse(readFileSync18(settingsPath, "utf-8"));
25276
+ return JSON.parse(readFileSync19(settingsPath, "utf-8"));
25253
25277
  }
25254
25278
  } catch {
25255
25279
  }
@@ -25280,7 +25304,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
25280
25304
  if (existsSync26(filePath) && !seen.has(filePath)) {
25281
25305
  seen.add(filePath);
25282
25306
  try {
25283
- let content = readFileSync18(filePath, "utf-8");
25307
+ let content = readFileSync19(filePath, "utf-8");
25284
25308
  if (content.length > maxContentLen) {
25285
25309
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
25286
25310
  }
@@ -25298,7 +25322,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
25298
25322
  if (existsSync26(projectMap) && !seen.has(projectMap)) {
25299
25323
  seen.add(projectMap);
25300
25324
  try {
25301
- let content = readFileSync18(projectMap, "utf-8");
25325
+ let content = readFileSync19(projectMap, "utf-8");
25302
25326
  if (content.length > maxContentLen) {
25303
25327
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
25304
25328
  }
@@ -25330,7 +25354,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
25330
25354
  function readIndexMeta(repoRoot) {
25331
25355
  const metaPath = join36(repoRoot, OA_DIR, "index", "meta.json");
25332
25356
  try {
25333
- return JSON.parse(readFileSync18(metaPath, "utf-8"));
25357
+ return JSON.parse(readFileSync19(metaPath, "utf-8"));
25334
25358
  } catch {
25335
25359
  return null;
25336
25360
  }
@@ -25402,7 +25426,7 @@ function loadRecentSessions(repoRoot, limit = 5) {
25402
25426
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
25403
25427
  return files.map((f) => {
25404
25428
  try {
25405
- return JSON.parse(readFileSync18(join36(historyDir, f.file), "utf-8"));
25429
+ return JSON.parse(readFileSync19(join36(historyDir, f.file), "utf-8"));
25406
25430
  } catch {
25407
25431
  return null;
25408
25432
  }
@@ -25421,7 +25445,7 @@ function loadPendingTask(repoRoot) {
25421
25445
  try {
25422
25446
  if (!existsSync26(filePath))
25423
25447
  return null;
25424
- const data = JSON.parse(readFileSync18(filePath, "utf-8"));
25448
+ const data = JSON.parse(readFileSync19(filePath, "utf-8"));
25425
25449
  try {
25426
25450
  unlinkSync3(filePath);
25427
25451
  } catch {
@@ -25438,7 +25462,7 @@ function saveSessionContext(repoRoot, entry) {
25438
25462
  let ctx;
25439
25463
  try {
25440
25464
  if (existsSync26(filePath)) {
25441
- ctx = JSON.parse(readFileSync18(filePath, "utf-8"));
25465
+ ctx = JSON.parse(readFileSync19(filePath, "utf-8"));
25442
25466
  } else {
25443
25467
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
25444
25468
  }
@@ -25457,7 +25481,7 @@ function loadSessionContext(repoRoot) {
25457
25481
  try {
25458
25482
  if (!existsSync26(filePath))
25459
25483
  return null;
25460
- return JSON.parse(readFileSync18(filePath, "utf-8"));
25484
+ return JSON.parse(readFileSync19(filePath, "utf-8"));
25461
25485
  } catch {
25462
25486
  return null;
25463
25487
  }
@@ -25509,7 +25533,7 @@ function detectManifests(repoRoot) {
25509
25533
  let name;
25510
25534
  if (check.nameField) {
25511
25535
  try {
25512
- const data = JSON.parse(readFileSync18(filePath, "utf-8"));
25536
+ const data = JSON.parse(readFileSync19(filePath, "utf-8"));
25513
25537
  name = data[check.nameField];
25514
25538
  } catch {
25515
25539
  }
@@ -28599,7 +28623,7 @@ var init_commands = __esm({
28599
28623
  });
28600
28624
 
28601
28625
  // packages/cli/dist/tui/project-context.js
28602
- import { existsSync as existsSync28, readFileSync as readFileSync19, readdirSync as readdirSync8 } from "node:fs";
28626
+ import { existsSync as existsSync28, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
28603
28627
  import { join as join38, basename as basename10 } from "node:path";
28604
28628
  import { execSync as execSync25 } from "node:child_process";
28605
28629
  import { homedir as homedir11, platform as platform2, release } from "node:os";
@@ -28638,7 +28662,7 @@ function loadProjectMap(repoRoot) {
28638
28662
  const mapPath = join38(repoRoot, OA_DIR, "context", "project-map.md");
28639
28663
  if (existsSync28(mapPath)) {
28640
28664
  try {
28641
- const content = readFileSync19(mapPath, "utf-8");
28665
+ const content = readFileSync20(mapPath, "utf-8");
28642
28666
  return content;
28643
28667
  } catch {
28644
28668
  }
@@ -28703,7 +28727,7 @@ function loadMemoryDir(memDir, scope) {
28703
28727
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
28704
28728
  for (const file of files.slice(0, 10)) {
28705
28729
  try {
28706
- const raw = readFileSync19(join38(memDir, file), "utf-8");
28730
+ const raw = readFileSync20(join38(memDir, file), "utf-8");
28707
28731
  const entries = JSON.parse(raw);
28708
28732
  const topic = basename10(file, ".json");
28709
28733
  const keys = Object.keys(entries);
@@ -29730,14 +29754,14 @@ var init_carousel = __esm({
29730
29754
  });
29731
29755
 
29732
29756
  // packages/cli/dist/tui/carousel-descriptors.js
29733
- import { existsSync as existsSync29, readFileSync as readFileSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
29757
+ import { existsSync as existsSync29, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
29734
29758
  import { join as join39, basename as basename11 } from "node:path";
29735
29759
  function loadToolProfile(repoRoot) {
29736
29760
  const filePath = join39(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
29737
29761
  try {
29738
29762
  if (!existsSync29(filePath))
29739
29763
  return null;
29740
- return JSON.parse(readFileSync20(filePath, "utf-8"));
29764
+ return JSON.parse(readFileSync21(filePath, "utf-8"));
29741
29765
  } catch {
29742
29766
  return null;
29743
29767
  }
@@ -29807,7 +29831,7 @@ function loadCachedDescriptors(repoRoot) {
29807
29831
  try {
29808
29832
  if (!existsSync29(filePath))
29809
29833
  return null;
29810
- const cached = JSON.parse(readFileSync20(filePath, "utf-8"));
29834
+ const cached = JSON.parse(readFileSync21(filePath, "utf-8"));
29811
29835
  return cached.phrases.length > 0 ? cached.phrases : null;
29812
29836
  } catch {
29813
29837
  return null;
@@ -29873,7 +29897,7 @@ function extractFromPackageJson(repoRoot, tags) {
29873
29897
  try {
29874
29898
  if (!existsSync29(pkgPath))
29875
29899
  return;
29876
- const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
29900
+ const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
29877
29901
  if (pkg.name && typeof pkg.name === "string") {
29878
29902
  const parts = pkg.name.replace(/^@/, "").split("/");
29879
29903
  for (const p of parts)
@@ -29948,7 +29972,7 @@ function extractFromMemory(repoRoot, tags) {
29948
29972
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
29949
29973
  tags.push(topic);
29950
29974
  try {
29951
- const data = JSON.parse(readFileSync20(join39(memoryDir, file), "utf-8"));
29975
+ const data = JSON.parse(readFileSync21(join39(memoryDir, file), "utf-8"));
29952
29976
  if (data && typeof data === "object") {
29953
29977
  const keys = Object.keys(data).slice(0, 3);
29954
29978
  for (const key of keys) {
@@ -30083,7 +30107,7 @@ var init_carousel_descriptors = __esm({
30083
30107
  });
30084
30108
 
30085
30109
  // packages/cli/dist/tui/voice.js
30086
- import { existsSync as existsSync30, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync21, unlinkSync as unlinkSync4 } from "node:fs";
30110
+ import { existsSync as existsSync30, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
30087
30111
  import { join as join40 } from "node:path";
30088
30112
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
30089
30113
  import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
@@ -31037,7 +31061,7 @@ var init_voice = __esm({
31037
31061
  };
31038
31062
  if (existsSync30(pkgPath)) {
31039
31063
  try {
31040
- const existing = JSON.parse(readFileSync21(pkgPath, "utf8"));
31064
+ const existing = JSON.parse(readFileSync22(pkgPath, "utf8"));
31041
31065
  if (!existing.dependencies?.["phonemizer"]) {
31042
31066
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
31043
31067
  writeFileSync11(pkgPath, JSON.stringify(existing, null, 2));
@@ -31181,7 +31205,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
31181
31205
  if (!existsSync30(onnxPath) || !existsSync30(configPath)) {
31182
31206
  throw new Error(`Model files not found for ${this.modelId}`);
31183
31207
  }
31184
- this.config = JSON.parse(readFileSync21(configPath, "utf8"));
31208
+ this.config = JSON.parse(readFileSync22(configPath, "utf8"));
31185
31209
  renderInfo("Loading voice model...");
31186
31210
  this.session = await this.ort.InferenceSession.create(onnxPath, {
31187
31211
  executionProviders: ["cpu"],
@@ -32159,7 +32183,7 @@ var init_edit_history = __esm({
32159
32183
  });
32160
32184
 
32161
32185
  // packages/cli/dist/tui/promptLoader.js
32162
- import { readFileSync as readFileSync22, existsSync as existsSync31 } from "node:fs";
32186
+ import { readFileSync as readFileSync23, existsSync as existsSync31 } from "node:fs";
32163
32187
  import { join as join42, dirname as dirname15 } from "node:path";
32164
32188
  import { fileURLToPath as fileURLToPath11 } from "node:url";
32165
32189
  function loadPrompt3(promptPath, vars) {
@@ -32169,7 +32193,7 @@ function loadPrompt3(promptPath, vars) {
32169
32193
  if (!existsSync31(fullPath)) {
32170
32194
  throw new Error(`Prompt file not found: ${fullPath}`);
32171
32195
  }
32172
- content = readFileSync22(fullPath, "utf-8");
32196
+ content = readFileSync23(fullPath, "utf-8");
32173
32197
  cache3.set(promptPath, content);
32174
32198
  }
32175
32199
  if (!vars)
@@ -32190,7 +32214,7 @@ var init_promptLoader3 = __esm({
32190
32214
  });
32191
32215
 
32192
32216
  // packages/cli/dist/tui/dream-engine.js
32193
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync23, existsSync as existsSync32, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
32217
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync32, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
32194
32218
  import { join as join43, basename as basename12 } from "node:path";
32195
32219
  import { execSync as execSync27 } from "node:child_process";
32196
32220
  function loadAutoresearchMemory(repoRoot) {
@@ -32198,7 +32222,7 @@ function loadAutoresearchMemory(repoRoot) {
32198
32222
  if (!existsSync32(memoryPath))
32199
32223
  return "";
32200
32224
  try {
32201
- const raw = readFileSync23(memoryPath, "utf-8");
32225
+ const raw = readFileSync24(memoryPath, "utf-8");
32202
32226
  const data = JSON.parse(raw);
32203
32227
  const sections = [];
32204
32228
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -32431,7 +32455,7 @@ var init_dream_engine = __esm({
32431
32455
  if (!existsSync32(targetPath)) {
32432
32456
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
32433
32457
  }
32434
- let content = readFileSync23(targetPath, "utf-8");
32458
+ let content = readFileSync24(targetPath, "utf-8");
32435
32459
  if (!content.includes(oldStr)) {
32436
32460
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
32437
32461
  }
@@ -32520,7 +32544,7 @@ var init_dream_engine = __esm({
32520
32544
  if (!existsSync32(targetPath)) {
32521
32545
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
32522
32546
  }
32523
- let content = readFileSync23(targetPath, "utf-8");
32547
+ let content = readFileSync24(targetPath, "utf-8");
32524
32548
  if (!content.includes(oldStr)) {
32525
32549
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
32526
32550
  }
@@ -33798,7 +33822,7 @@ var init_bless_engine = __esm({
33798
33822
  });
33799
33823
 
33800
33824
  // packages/cli/dist/tui/dmn-engine.js
33801
- import { existsSync as existsSync33, readFileSync as readFileSync24, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
33825
+ import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
33802
33826
  import { join as join44, basename as basename13 } from "node:path";
33803
33827
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
33804
33828
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
@@ -34526,7 +34550,7 @@ OUTPUT: Call task_complete with JSON:
34526
34550
  const path = join44(this.stateDir, "state.json");
34527
34551
  if (existsSync33(path)) {
34528
34552
  try {
34529
- this.state = JSON.parse(readFileSync24(path, "utf-8"));
34553
+ this.state = JSON.parse(readFileSync25(path, "utf-8"));
34530
34554
  } catch {
34531
34555
  }
34532
34556
  }
@@ -34558,7 +34582,7 @@ OUTPUT: Call task_complete with JSON:
34558
34582
  });
34559
34583
 
34560
34584
  // packages/cli/dist/tui/snr-engine.js
34561
- import { existsSync as existsSync34, readdirSync as readdirSync12, readFileSync as readFileSync25 } from "node:fs";
34585
+ import { existsSync as existsSync34, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
34562
34586
  import { join as join45, basename as basename14 } from "node:path";
34563
34587
  function computeDPrime(signalScores, noiseScores) {
34564
34588
  if (signalScores.length === 0 || noiseScores.length === 0)
@@ -34812,7 +34836,7 @@ Call task_complete with the JSON array when done.`, onEvent)
34812
34836
  if (topics.length > 0 && !topics.includes(topic))
34813
34837
  continue;
34814
34838
  try {
34815
- const data = JSON.parse(readFileSync25(join45(dir, f), "utf-8"));
34839
+ const data = JSON.parse(readFileSync26(join45(dir, f), "utf-8"));
34816
34840
  for (const [key, val] of Object.entries(data)) {
34817
34841
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
34818
34842
  entries.push({ topic, key, value });
@@ -35866,7 +35890,8 @@ with summary "no_reply" to silently skip without responding.
35866
35890
  existing.runner.injectUserMessage(msg.text);
35867
35891
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "mid-conversation steering injected"));
35868
35892
  } else {
35869
- this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "queued (sub-agent still starting)"));
35893
+ existing.pendingMessages.push(msg.text);
35894
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `queued (${existing.pendingMessages.length} pending)`));
35870
35895
  }
35871
35896
  return;
35872
35897
  }
@@ -35880,7 +35905,8 @@ with summary "no_reply" to silently skip without responding.
35880
35905
  intermediateLines: [],
35881
35906
  lastEditMs: 0,
35882
35907
  aborted: false,
35883
- toolContext
35908
+ toolContext,
35909
+ pendingMessages: []
35884
35910
  };
35885
35911
  this.subAgents.set(msg.chatId, subAgent);
35886
35912
  this.state.activeSubAgents = this.subAgents.size;
@@ -35953,6 +35979,13 @@ with summary "no_reply" to silently skip without responding.
35953
35979
  streamEnabled: true
35954
35980
  });
35955
35981
  subAgent.runner = runner;
35982
+ if (subAgent.pendingMessages.length > 0) {
35983
+ for (const queued of subAgent.pendingMessages) {
35984
+ runner.injectUserMessage(queued);
35985
+ }
35986
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `replayed ${subAgent.pendingMessages.length} queued message(s)`));
35987
+ subAgent.pendingMessages.length = 0;
35988
+ }
35956
35989
  const tools = this.buildSubAgentTools(ctx, repoRoot, msg.chatId);
35957
35990
  runner.registerTools(tools);
35958
35991
  runner.onEvent((event) => {
@@ -37845,7 +37878,7 @@ import { cwd } from "node:process";
37845
37878
  import { resolve as resolve28, join as join47, dirname as dirname16, extname as extname9 } from "node:path";
37846
37879
  import { createRequire as createRequire2 } from "node:module";
37847
37880
  import { fileURLToPath as fileURLToPath12 } from "node:url";
37848
- import { readFileSync as readFileSync26, rmSync as rmSync2, readdirSync as readdirSync14 } from "node:fs";
37881
+ import { readFileSync as readFileSync27, rmSync as rmSync2, readdirSync as readdirSync14 } from "node:fs";
37849
37882
  import { existsSync as existsSync36 } from "node:fs";
37850
37883
  function formatTimeAgo(date) {
37851
37884
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -38077,7 +38110,7 @@ function gatherMemorySnippets(root) {
38077
38110
  continue;
38078
38111
  try {
38079
38112
  for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
38080
- const data = JSON.parse(readFileSync26(join47(dir, f), "utf-8"));
38113
+ const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
38081
38114
  for (const val of Object.values(data)) {
38082
38115
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
38083
38116
  if (v.length > 10)
@@ -39821,10 +39854,24 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
39821
39854
  writeContent(() => {
39822
39855
  renderInfo(`Previous session found (${savedCtx.entries.length} entries, last active ${timeAgo})`);
39823
39856
  renderInfo(`Last task: ${lastTask}${lastEntry.task && lastEntry.task.length > 80 ? "..." : ""}`);
39824
- renderInfo(`Restore previous context? (y/n)`);
39857
+ renderInfo(`Restore previous context? (y/n) [auto-restores in 15s]`);
39825
39858
  });
39826
39859
  showPrompt();
39827
39860
  pendingSessionRestore = true;
39861
+ setTimeout(() => {
39862
+ if (pendingSessionRestore) {
39863
+ pendingSessionRestore = false;
39864
+ const prompt = buildContextRestorePrompt(repoRoot);
39865
+ if (prompt) {
39866
+ restoredSessionContext = prompt;
39867
+ const info = loadSessionContext(repoRoot);
39868
+ writeContent(() => renderInfo(`Context auto-restored from ${info?.entries.length ?? 0} session(s).`));
39869
+ } else {
39870
+ writeContent(() => renderInfo("No context to restore. Starting fresh."));
39871
+ }
39872
+ showPrompt();
39873
+ }
39874
+ }, 15e3);
39828
39875
  }, 150);
39829
39876
  }
39830
39877
  }
@@ -40058,7 +40105,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
40058
40105
  if (isImage) {
40059
40106
  try {
40060
40107
  const imgPath = resolve28(repoRoot, cleanPath);
40061
- const imgBuffer = readFileSync26(imgPath);
40108
+ const imgBuffer = readFileSync27(imgPath);
40062
40109
  const base64 = imgBuffer.toString("base64");
40063
40110
  const ext = extname9(cleanPath).toLowerCase();
40064
40111
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.79.0",
3
+ "version": "0.80.0",
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",