open-agents-ai 0.187.536 → 0.187.537

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.
package/dist/index.js CHANGED
@@ -247827,9 +247827,9 @@ print("${sentinel}")
247827
247827
  if (!this.proc || this.proc.killed) {
247828
247828
  return { success: false, path: "" };
247829
247829
  }
247830
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
247830
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
247831
247831
  const sessionDir = join28(this.cwd, ".oa", "rlm");
247832
- mkdirSync67(sessionDir, { recursive: true });
247832
+ mkdirSync68(sessionDir, { recursive: true });
247833
247833
  const sessionPath2 = join28(sessionDir, "session.json");
247834
247834
  try {
247835
247835
  const inspectCode = `
@@ -247853,7 +247853,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
247853
247853
  trajectoryCount: this.trajectory.length,
247854
247854
  subCallCount: this.subCallCount
247855
247855
  };
247856
- writeFileSync59(sessionPath2, JSON.stringify(sessionData, null, 2), "utf8");
247856
+ writeFileSync60(sessionPath2, JSON.stringify(sessionData, null, 2), "utf8");
247857
247857
  return { success: true, path: sessionPath2 };
247858
247858
  }
247859
247859
  } catch {
@@ -247865,9 +247865,9 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
247865
247865
  * what was previously computed. */
247866
247866
  async loadSessionInfo() {
247867
247867
  try {
247868
- const { readFileSync: readFileSync89, existsSync: existsSync110 } = await import("node:fs");
247868
+ const { readFileSync: readFileSync89, existsSync: existsSync111 } = await import("node:fs");
247869
247869
  const sessionPath2 = join28(this.cwd, ".oa", "rlm", "session.json");
247870
- if (!existsSync110(sessionPath2))
247870
+ if (!existsSync111(sessionPath2))
247871
247871
  return null;
247872
247872
  return JSON.parse(readFileSync89(sessionPath2, "utf8"));
247873
247873
  } catch {
@@ -248433,10 +248433,10 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
248433
248433
  * Optionally filter by task type for phase-aware context (FSM paper insight).
248434
248434
  */
248435
248435
  getTopMemoriesSync(k = 5, taskType) {
248436
- const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
248436
+ const { readFileSync: readFileSync89, existsSync: existsSync111 } = __require("node:fs");
248437
248437
  const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
248438
248438
  const storeFile = join29(metaDir, "store.json");
248439
- if (!existsSync110(storeFile))
248439
+ if (!existsSync111(storeFile))
248440
248440
  return "";
248441
248441
  let store2 = [];
248442
248442
  try {
@@ -248462,10 +248462,10 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
248462
248462
  /** Update memory scores based on task outcome. Called after task completion.
248463
248463
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
248464
248464
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
248465
- const { readFileSync: readFileSync89, writeFileSync: writeFileSync59, existsSync: existsSync110, mkdirSync: mkdirSync67 } = __require("node:fs");
248465
+ const { readFileSync: readFileSync89, writeFileSync: writeFileSync60, existsSync: existsSync111, mkdirSync: mkdirSync68 } = __require("node:fs");
248466
248466
  const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
248467
248467
  const storeFile = join29(metaDir, "store.json");
248468
- if (!existsSync110(storeFile))
248468
+ if (!existsSync111(storeFile))
248469
248469
  return;
248470
248470
  let store2 = [];
248471
248471
  try {
@@ -248493,8 +248493,8 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
248493
248493
  updated = true;
248494
248494
  }
248495
248495
  if (updated) {
248496
- mkdirSync67(metaDir, { recursive: true });
248497
- writeFileSync59(storeFile, JSON.stringify(store2, null, 2));
248496
+ mkdirSync68(metaDir, { recursive: true });
248497
+ writeFileSync60(storeFile, JSON.stringify(store2, null, 2));
248498
248498
  }
248499
248499
  }
248500
248500
  // ── Storage ──────────────────────────────────────────────────────────
@@ -248916,9 +248916,9 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
248916
248916
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
248917
248917
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
248918
248918
  getRelevantStrategiesSync(k = 3, taskType) {
248919
- const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
248919
+ const { readFileSync: readFileSync89, existsSync: existsSync111 } = __require("node:fs");
248920
248920
  const archiveFile = join31(this.cwd, ".oa", "arche", "variants.json");
248921
- if (!existsSync110(archiveFile))
248921
+ if (!existsSync111(archiveFile))
248922
248922
  return "";
248923
248923
  let variants = [];
248924
248924
  try {
@@ -248940,12 +248940,12 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
248940
248940
  }
248941
248941
  /** Archive a strategy variant synchronously (for task completion path) */
248942
248942
  archiveVariantSync(strategy, outcome, tags = []) {
248943
- const { readFileSync: readFileSync89, writeFileSync: writeFileSync59, existsSync: existsSync110, mkdirSync: mkdirSync67 } = __require("node:fs");
248943
+ const { readFileSync: readFileSync89, writeFileSync: writeFileSync60, existsSync: existsSync111, mkdirSync: mkdirSync68 } = __require("node:fs");
248944
248944
  const dir = join31(this.cwd, ".oa", "arche");
248945
248945
  const archiveFile = join31(dir, "variants.json");
248946
248946
  let variants = [];
248947
248947
  try {
248948
- if (existsSync110(archiveFile))
248948
+ if (existsSync111(archiveFile))
248949
248949
  variants = JSON.parse(readFileSync89(archiveFile, "utf8"));
248950
248950
  } catch {
248951
248951
  }
@@ -248961,8 +248961,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
248961
248961
  });
248962
248962
  if (variants.length > 50)
248963
248963
  variants = variants.slice(-50);
248964
- mkdirSync67(dir, { recursive: true });
248965
- writeFileSync59(archiveFile, JSON.stringify(variants, null, 2));
248964
+ mkdirSync68(dir, { recursive: true });
248965
+ writeFileSync60(archiveFile, JSON.stringify(variants, null, 2));
248966
248966
  }
248967
248967
  async saveArchive(variants) {
248968
248968
  const dir = join31(this.cwd, ".oa", "arche");
@@ -257226,7 +257226,7 @@ var require_util9 = __commonJS({
257226
257226
  return path8;
257227
257227
  }
257228
257228
  exports.normalize = normalize2;
257229
- function join128(aRoot, aPath) {
257229
+ function join129(aRoot, aPath) {
257230
257230
  if (aRoot === "") {
257231
257231
  aRoot = ".";
257232
257232
  }
@@ -257258,7 +257258,7 @@ var require_util9 = __commonJS({
257258
257258
  }
257259
257259
  return joined;
257260
257260
  }
257261
- exports.join = join128;
257261
+ exports.join = join129;
257262
257262
  exports.isAbsolute = function(aPath) {
257263
257263
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
257264
257264
  };
@@ -257431,7 +257431,7 @@ var require_util9 = __commonJS({
257431
257431
  parsed.path = parsed.path.substring(0, index + 1);
257432
257432
  }
257433
257433
  }
257434
- sourceURL = join128(urlGenerate(parsed), sourceURL);
257434
+ sourceURL = join129(urlGenerate(parsed), sourceURL);
257435
257435
  }
257436
257436
  return normalize2(sourceURL);
257437
257437
  }
@@ -472334,10 +472334,10 @@ var require_commonjs3 = __commonJS({
472334
472334
  let ai = 0;
472335
472335
  let bi = 0;
472336
472336
  let result = [];
472337
- let which = "";
472337
+ let which2 = "";
472338
472338
  while (ai < a2.length && bi < b.length) {
472339
472339
  if (a2[ai] === b[bi]) {
472340
- result.push(which === "b" ? b[bi] : a2[ai]);
472340
+ result.push(which2 === "b" ? b[bi] : a2[ai]);
472341
472341
  ai++;
472342
472342
  bi++;
472343
472343
  } else if (emptyGSMatch && a2[ai] === "**" && b[bi] === a2[ai + 1]) {
@@ -472347,16 +472347,16 @@ var require_commonjs3 = __commonJS({
472347
472347
  result.push(b[bi]);
472348
472348
  bi++;
472349
472349
  } else if (a2[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") {
472350
- if (which === "b")
472350
+ if (which2 === "b")
472351
472351
  return false;
472352
- which = "a";
472352
+ which2 = "a";
472353
472353
  result.push(a2[ai]);
472354
472354
  ai++;
472355
472355
  bi++;
472356
472356
  } else if (b[bi] === "*" && a2[ai] && (this.options.dot || !a2[ai].startsWith(".")) && a2[ai] !== "**") {
472357
- if (which === "a")
472357
+ if (which2 === "a")
472358
472358
  return false;
472359
- which = "b";
472359
+ which2 = "b";
472360
472360
  result.push(b[bi]);
472361
472361
  ai++;
472362
472362
  bi++;
@@ -472851,7 +472851,7 @@ var require_path_browserify = __commonJS({
472851
472851
  assertPath(path8);
472852
472852
  return path8.length > 0 && path8.charCodeAt(0) === 47;
472853
472853
  },
472854
- join: function join128() {
472854
+ join: function join129() {
472855
472855
  if (arguments.length === 0)
472856
472856
  return ".";
472857
472857
  var joined;
@@ -507839,7 +507839,7 @@ var init_agent_tool = __esm({
507839
507839
  })();
507840
507840
  if (isolation === "worktree") {
507841
507841
  this.callbacks.onViewRegister?.(agentId, label);
507842
- const spawn27 = this.callbacks.spawnSubprocess({
507842
+ const spawn28 = this.callbacks.spawnSubprocess({
507843
507843
  id: agentId,
507844
507844
  task: composedPrompt,
507845
507845
  model,
@@ -507849,7 +507849,7 @@ var init_agent_tool = __esm({
507849
507849
  success: true,
507850
507850
  output: `Agent spawned (subprocess, worktree): ${agentId}
507851
507851
  Type: ${subagentType}
507852
- PID: ${spawn27.pid}
507852
+ PID: ${spawn28.pid}
507853
507853
  Task: ${prompt.slice(0, 100)}
507854
507854
  Use task_status("${agentId}") to check progress.`,
507855
507855
  durationMs: performance.now() - start2
@@ -522965,8 +522965,8 @@ var init_reflectionBuffer = __esm({
522965
522965
  this.persistPath = persistPath ?? null;
522966
522966
  if (this.persistPath) {
522967
522967
  try {
522968
- const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
522969
- if (existsSync110(this.persistPath)) {
522968
+ const { readFileSync: readFileSync89, existsSync: existsSync111 } = __require("node:fs");
522969
+ if (existsSync111(this.persistPath)) {
522970
522970
  this.state = JSON.parse(readFileSync89(this.persistPath, "utf-8"));
522971
522971
  return;
522972
522972
  }
@@ -523200,12 +523200,12 @@ var init_reflectionBuffer = __esm({
523200
523200
  if (!this.persistPath)
523201
523201
  return;
523202
523202
  try {
523203
- const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: existsSync110 } = __require("node:fs");
523204
- const { join: join128 } = __require("node:path");
523205
- const dir = join128(this.persistPath, "..");
523206
- if (!existsSync110(dir))
523207
- mkdirSync67(dir, { recursive: true });
523208
- writeFileSync59(this.persistPath, JSON.stringify(this.state, null, 2));
523203
+ const { writeFileSync: writeFileSync60, mkdirSync: mkdirSync68, existsSync: existsSync111 } = __require("node:fs");
523204
+ const { join: join129 } = __require("node:path");
523205
+ const dir = join129(this.persistPath, "..");
523206
+ if (!existsSync111(dir))
523207
+ mkdirSync68(dir, { recursive: true });
523208
+ writeFileSync60(this.persistPath, JSON.stringify(this.state, null, 2));
523209
523209
  } catch {
523210
523210
  }
523211
523211
  }
@@ -533745,10 +533745,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
533745
533745
  if (nodes > 0) {
533746
533746
  this.emit({ type: "status", content: `Knowledge graph: ${nodes} nodes, ${edges} active edges`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533747
533747
  try {
533748
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
533749
- const { join: join128 } = __require("node:path");
533750
- const contextDir = join128(this._workingDirectory || process.cwd(), ".oa", "context");
533751
- mkdirSync67(contextDir, { recursive: true });
533748
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = __require("node:fs");
533749
+ const { join: join129 } = __require("node:path");
533750
+ const contextDir = join129(this._workingDirectory || process.cwd(), ".oa", "context");
533751
+ mkdirSync68(contextDir, { recursive: true });
533752
533752
  const topEntities = this._temporalGraph.nodesByType("entity", 3);
533753
533753
  const topFiles = this._temporalGraph.nodesByType("file", 3);
533754
533754
  const topConcepts = this._temporalGraph.nodesByType("concept", 3);
@@ -533788,9 +533788,9 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
533788
533788
  section("Top Files", topFiles);
533789
533789
  section("Top Concepts", topConcepts);
533790
533790
  lines.push("(Use file_read on this file for quick recall. See provenance JSON for full edge detail.)");
533791
- const outPath = join128(contextDir, `kg-summary-${this._sessionId}.md`);
533792
- writeFileSync59(outPath, lines.join("\n"), "utf-8");
533793
- writeFileSync59(join128(contextDir, `kg-summary-latest.md`), lines.join("\n"), "utf-8");
533791
+ const outPath = join129(contextDir, `kg-summary-${this._sessionId}.md`);
533792
+ writeFileSync60(outPath, lines.join("\n"), "utf-8");
533793
+ writeFileSync60(join129(contextDir, `kg-summary-latest.md`), lines.join("\n"), "utf-8");
533794
533794
  } catch {
533795
533795
  }
533796
533796
  }
@@ -533958,11 +533958,11 @@ ${errOutput}`;
533958
533958
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
533959
533959
  });
533960
533960
  try {
533961
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
533962
- const { join: join128 } = __require("node:path");
533963
- const resultsDir = join128(process.cwd(), ".oa", "tool-results");
533964
- mkdirSync67(resultsDir, { recursive: true });
533965
- writeFileSync59(join128(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
533961
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = __require("node:fs");
533962
+ const { join: join129 } = __require("node:path");
533963
+ const resultsDir = join129(process.cwd(), ".oa", "tool-results");
533964
+ mkdirSync68(resultsDir, { recursive: true });
533965
+ writeFileSync60(join129(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
533966
533966
  # Turn: ${turn}
533967
533967
  # Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
533968
533968
  # Size: ${result.output.length} chars, ${lineCount} lines
@@ -534178,10 +534178,10 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
534178
534178
  if (!this._workingDirectory)
534179
534179
  return;
534180
534180
  try {
534181
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
534182
- const { join: join128 } = __require("node:path");
534183
- const sessionDir = join128(this._workingDirectory, ".oa", "session", this._sessionId);
534184
- mkdirSync67(sessionDir, { recursive: true });
534181
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = __require("node:fs");
534182
+ const { join: join129 } = __require("node:path");
534183
+ const sessionDir = join129(this._workingDirectory, ".oa", "session", this._sessionId);
534184
+ mkdirSync68(sessionDir, { recursive: true });
534185
534185
  const checkpoint = {
534186
534186
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
534187
534187
  sessionId: this._sessionId,
@@ -534193,7 +534193,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
534193
534193
  memexEntryCount: this._memexArchive.size,
534194
534194
  fileRegistrySize: this._fileRegistry.size
534195
534195
  };
534196
- writeFileSync59(join128(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
534196
+ writeFileSync60(join129(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
534197
534197
  } catch {
534198
534198
  }
534199
534199
  }
@@ -536020,12 +536020,12 @@ ${result}`
536020
536020
  let resizedBase64 = null;
536021
536021
  try {
536022
536022
  const { execSync: execSync59 } = await import("node:child_process");
536023
- const { writeFileSync: writeFileSync59, readFileSync: readFileSync89, unlinkSync: unlinkSync25 } = await import("node:fs");
536024
- const { join: join128 } = await import("node:path");
536025
- const { tmpdir: tmpdir22 } = await import("node:os");
536026
- const tmpIn = join128(tmpdir22(), `oa_img_in_${Date.now()}.png`);
536027
- const tmpOut = join128(tmpdir22(), `oa_img_out_${Date.now()}.jpg`);
536028
- writeFileSync59(tmpIn, buffer2);
536023
+ const { writeFileSync: writeFileSync60, readFileSync: readFileSync89, unlinkSync: unlinkSync25 } = await import("node:fs");
536024
+ const { join: join129 } = await import("node:path");
536025
+ const { tmpdir: tmpdir23 } = await import("node:os");
536026
+ const tmpIn = join129(tmpdir23(), `oa_img_in_${Date.now()}.png`);
536027
+ const tmpOut = join129(tmpdir23(), `oa_img_out_${Date.now()}.jpg`);
536028
+ writeFileSync60(tmpIn, buffer2);
536029
536029
  const pyBin = process.platform === "win32" ? "python" : "python3";
536030
536030
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
536031
536031
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
@@ -544570,23 +544570,23 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
544570
544570
  async function fetchPeerModels(peerId, authKey) {
544571
544571
  try {
544572
544572
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
544573
- const { existsSync: existsSync110, readFileSync: readFileSync89 } = await import("node:fs");
544574
- const { join: join128 } = await import("node:path");
544573
+ const { existsSync: existsSync111, readFileSync: readFileSync89 } = await import("node:fs");
544574
+ const { join: join129 } = await import("node:path");
544575
544575
  const cwd4 = process.cwd();
544576
544576
  const nexusTool = new NexusTool2(cwd4);
544577
544577
  const nexusDir = nexusTool.getNexusDir();
544578
544578
  let isLocalPeer = false;
544579
544579
  try {
544580
- const statusPath = join128(nexusDir, "status.json");
544581
- if (existsSync110(statusPath)) {
544580
+ const statusPath = join129(nexusDir, "status.json");
544581
+ if (existsSync111(statusPath)) {
544582
544582
  const status = JSON.parse(readFileSync89(statusPath, "utf8"));
544583
544583
  if (status.peerId === peerId) isLocalPeer = true;
544584
544584
  }
544585
544585
  } catch {
544586
544586
  }
544587
544587
  if (isLocalPeer) {
544588
- const pricingPath = join128(nexusDir, "pricing.json");
544589
- if (existsSync110(pricingPath)) {
544588
+ const pricingPath = join129(nexusDir, "pricing.json");
544589
+ if (existsSync111(pricingPath)) {
544590
544590
  try {
544591
544591
  const pricing = JSON.parse(readFileSync89(pricingPath, "utf8"));
544592
544592
  const localModels = (pricing.models || []).map((m2) => ({
@@ -544601,8 +544601,8 @@ async function fetchPeerModels(peerId, authKey) {
544601
544601
  }
544602
544602
  }
544603
544603
  }
544604
- const cachePath = join128(nexusDir, "peer-models-cache.json");
544605
- if (existsSync110(cachePath)) {
544604
+ const cachePath = join129(nexusDir, "peer-models-cache.json");
544605
+ if (existsSync111(cachePath)) {
544606
544606
  try {
544607
544607
  const cache8 = JSON.parse(readFileSync89(cachePath, "utf8"));
544608
544608
  if (cache8.peerId === peerId && cache8.models?.length > 0) {
@@ -544716,8 +544716,8 @@ async function fetchPeerModels(peerId, authKey) {
544716
544716
  } catch {
544717
544717
  }
544718
544718
  if (isLocalPeer) {
544719
- const pricingPath = join128(nexusDir, "pricing.json");
544720
- if (existsSync110(pricingPath)) {
544719
+ const pricingPath = join129(nexusDir, "pricing.json");
544720
+ if (existsSync111(pricingPath)) {
544721
544721
  try {
544722
544722
  const pricing = JSON.parse(readFileSync89(pricingPath, "utf8"));
544723
544723
  return (pricing.models || []).map((m2) => ({
@@ -562498,13 +562498,13 @@ async function runSudoScript(ctx3, script) {
562498
562498
  } catch {
562499
562499
  }
562500
562500
  try {
562501
- const { spawn: spawn27 } = await import("node:child_process");
562501
+ const { spawn: spawn28 } = await import("node:child_process");
562502
562502
  const full = `set -e; ${script}`;
562503
562503
  await new Promise((resolve43) => {
562504
562504
  const usePkexec = process.platform === "linux";
562505
562505
  const cmd = usePkexec ? "pkexec" : "sudo";
562506
562506
  const args = usePkexec ? ["bash", "-lc", full] : ["-n", "bash", "-lc", full];
562507
- const child = spawn27(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
562507
+ const child = spawn28(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
562508
562508
  let stdout = "";
562509
562509
  let stderr = "";
562510
562510
  child.stdout?.on("data", (data) => {
@@ -562538,9 +562538,9 @@ async function ensureVoiceDeps(ctx3) {
562538
562538
  }
562539
562539
  if (typeof mod2.getVenvPython === "function") {
562540
562540
  const { dirname: dirname39 } = await import("node:path");
562541
- const { existsSync: existsSync110 } = await import("node:fs");
562541
+ const { existsSync: existsSync111 } = await import("node:fs");
562542
562542
  const venvPy = mod2.getVenvPython();
562543
- if (existsSync110(venvPy)) {
562543
+ if (existsSync111(venvPy)) {
562544
562544
  process.env.TRANSCRIBE_PYTHON = venvPy;
562545
562545
  const venvBin = dirname39(venvPy);
562546
562546
  const sep2 = process.platform === "win32" ? ";" : ":";
@@ -562859,10 +562859,10 @@ async function handleSlashCommand(input, ctx3) {
562859
562859
  if (!key) {
562860
562860
  try {
562861
562861
  const { homedir: homedir46 } = await import("node:os");
562862
- const { readFileSync: readFileSync89, existsSync: existsSync110 } = await import("node:fs");
562863
- const { join: join128 } = await import("node:path");
562864
- const p2 = join128(homedir46(), ".open-agents", "api.key");
562865
- if (existsSync110(p2)) key = readFileSync89(p2, "utf8").trim();
562862
+ const { readFileSync: readFileSync89, existsSync: existsSync111 } = await import("node:fs");
562863
+ const { join: join129 } = await import("node:path");
562864
+ const p2 = join129(homedir46(), ".open-agents", "api.key");
562865
+ if (existsSync111(p2)) key = readFileSync89(p2, "utf8").trim();
562866
562866
  } catch {
562867
562867
  }
562868
562868
  }
@@ -562901,13 +562901,13 @@ async function handleSlashCommand(input, ctx3) {
562901
562901
  try {
562902
562902
  const { randomBytes: randomBytes25 } = await import("node:crypto");
562903
562903
  const { homedir: homedir46 } = await import("node:os");
562904
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
562905
- const { join: join128 } = await import("node:path");
562904
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
562905
+ const { join: join129 } = await import("node:path");
562906
562906
  const newKey = randomBytes25(16).toString("hex");
562907
562907
  process.env["OA_API_KEY"] = newKey;
562908
- const dir = join128(homedir46(), ".open-agents");
562909
- mkdirSync67(dir, { recursive: true });
562910
- writeFileSync59(join128(dir, "api.key"), newKey + "\n", "utf8");
562908
+ const dir = join129(homedir46(), ".open-agents");
562909
+ mkdirSync68(dir, { recursive: true });
562910
+ writeFileSync60(join129(dir, "api.key"), newKey + "\n", "utf8");
562911
562911
  renderInfo2(`New API key: ${c3.bold(c3.yellow(newKey))}`);
562912
562912
  renderInfo2("Restart the daemon to apply if needed. Use /access any to restart quickly.");
562913
562913
  } catch (e2) {
@@ -563095,11 +563095,11 @@ async function handleSlashCommand(input, ctx3) {
563095
563095
  renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
563096
563096
  try {
563097
563097
  const { homedir: homedir47 } = await import("node:os");
563098
- const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
563099
- const { join: join129 } = await import("node:path");
563100
- const dir = join129(homedir47(), ".open-agents");
563101
- mkdirSync68(dir, { recursive: true });
563102
- writeFileSync60(join129(dir, "api.key"), apiKey + "\n", "utf8");
563098
+ const { mkdirSync: mkdirSync69, writeFileSync: writeFileSync61 } = await import("node:fs");
563099
+ const { join: join130 } = await import("node:path");
563100
+ const dir = join130(homedir47(), ".open-agents");
563101
+ mkdirSync69(dir, { recursive: true });
563102
+ writeFileSync61(join130(dir, "api.key"), apiKey + "\n", "utf8");
563103
563103
  } catch {
563104
563104
  }
563105
563105
  }
@@ -563111,11 +563111,11 @@ async function handleSlashCommand(input, ctx3) {
563111
563111
  const port2 = parseInt(process.env["OA_PORT"] || "11435", 10);
563112
563112
  try {
563113
563113
  const { homedir: homedir47 } = await import("node:os");
563114
- const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
563115
- const { join: join129 } = await import("node:path");
563116
- const dir = join129(homedir47(), ".open-agents");
563117
- mkdirSync68(dir, { recursive: true });
563118
- writeFileSync60(join129(dir, "access"), `${val2}
563114
+ const { mkdirSync: mkdirSync69, writeFileSync: writeFileSync61 } = await import("node:fs");
563115
+ const { join: join130 } = await import("node:path");
563116
+ const dir = join130(homedir47(), ".open-agents");
563117
+ mkdirSync69(dir, { recursive: true });
563118
+ writeFileSync61(join130(dir, "access"), `${val2}
563119
563119
  `, "utf8");
563120
563120
  } catch {
563121
563121
  }
@@ -563197,11 +563197,11 @@ async function handleSlashCommand(input, ctx3) {
563197
563197
  renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
563198
563198
  try {
563199
563199
  const { homedir: homedir47 } = await import("node:os");
563200
- const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
563201
- const { join: join129 } = await import("node:path");
563202
- const dir = join129(homedir47(), ".open-agents");
563203
- mkdirSync68(dir, { recursive: true });
563204
- writeFileSync60(join129(dir, "api.key"), apiKey + "\n", "utf8");
563200
+ const { mkdirSync: mkdirSync69, writeFileSync: writeFileSync61 } = await import("node:fs");
563201
+ const { join: join130 } = await import("node:path");
563202
+ const dir = join130(homedir47(), ".open-agents");
563203
+ mkdirSync69(dir, { recursive: true });
563204
+ writeFileSync61(join130(dir, "api.key"), apiKey + "\n", "utf8");
563205
563205
  } catch {
563206
563206
  }
563207
563207
  }
@@ -563212,12 +563212,12 @@ async function handleSlashCommand(input, ctx3) {
563212
563212
  }
563213
563213
  const port = parseInt(process.env["OA_PORT"] || "11435", 10);
563214
563214
  const { homedir: homedir46 } = await import("node:os");
563215
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
563216
- const { join: join128 } = await import("node:path");
563215
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
563216
+ const { join: join129 } = await import("node:path");
563217
563217
  try {
563218
- const dir = join128(homedir46(), ".open-agents");
563219
- mkdirSync67(dir, { recursive: true });
563220
- writeFileSync59(join128(dir, "access"), `${val}
563218
+ const dir = join129(homedir46(), ".open-agents");
563219
+ mkdirSync68(dir, { recursive: true });
563220
+ writeFileSync60(join129(dir, "access"), `${val}
563221
563221
  `, "utf8");
563222
563222
  } catch (e2) {
563223
563223
  renderWarning2(`Could not persist ~/.open-agents/access: ${e2 instanceof Error ? e2.message : String(e2)}`);
@@ -564269,8 +564269,8 @@ async function handleSlashCommand(input, ctx3) {
564269
564269
  writeFileSync41(jwtFile, JSON.stringify(jwtPayload, null, 2));
564270
564270
  renderInfo2(`Launching fortemi-react from ${fDir}...`);
564271
564271
  try {
564272
- const { spawn: spawn27 } = __require("node:child_process");
564273
- const child = spawn27("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
564272
+ const { spawn: spawn28 } = __require("node:child_process");
564273
+ const child = spawn28("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
564274
564274
  cwd: join99(fDir, "apps", "standalone"),
564275
564275
  stdio: "ignore",
564276
564276
  detached: true,
@@ -564995,9 +564995,9 @@ systemctl --user daemon-reload || true
564995
564995
  systemctl --user enable --now open-agents-daemon.service || true
564996
564996
  sleep 1
564997
564997
  `;
564998
- const { spawn: spawn27 } = await import("node:child_process");
564998
+ const { spawn: spawn28 } = await import("node:child_process");
564999
564999
  await new Promise((resolve43) => {
565000
- const child = spawn27("bash", ["-lc", takeover], { stdio: "inherit" });
565000
+ const child = spawn28("bash", ["-lc", takeover], { stdio: "inherit" });
565001
565001
  onChildExit(child, () => resolve43());
565002
565002
  });
565003
565003
  renderInfo2("Daemon takeover complete.");
@@ -567434,11 +567434,11 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
567434
567434
  continue;
567435
567435
  }
567436
567436
  const { basename: basename21, join: pathJoin } = await import("node:path");
567437
- const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync67, existsSync: exists2 } = await import("node:fs");
567437
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync68, existsSync: exists2 } = await import("node:fs");
567438
567438
  const { homedir: homedir46 } = await import("node:os");
567439
567439
  const modelName = basename21(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
567440
567440
  const destDir = pathJoin(homedir46(), ".open-agents", "voice", "models", modelName);
567441
- if (!exists2(destDir)) mkdirSync67(destDir, { recursive: true });
567441
+ if (!exists2(destDir)) mkdirSync68(destDir, { recursive: true });
567442
567442
  copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
567443
567443
  copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
567444
567444
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -568188,10 +568188,10 @@ async function handleSponsoredEndpoint(ctx3, local) {
568188
568188
  sponsors.push(...verified);
568189
568189
  if (verified.length > 0) {
568190
568190
  try {
568191
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
568192
- mkdirSync67(sponsorDir2, { recursive: true });
568191
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = __require("node:fs");
568192
+ mkdirSync68(sponsorDir2, { recursive: true });
568193
568193
  const cached = verified.map((s2) => ({ ...s2, lastVerified: Date.now() }));
568194
- writeFileSync59(knownFile, JSON.stringify(cached, null, 2));
568194
+ writeFileSync60(knownFile, JSON.stringify(cached, null, 2));
568195
568195
  } catch {
568196
568196
  }
568197
568197
  }
@@ -568364,11 +568364,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
568364
568364
  const models = await fetchModels(peerUrl, authKey);
568365
568365
  if (models.length > 0) {
568366
568366
  try {
568367
- const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67 } = await import("node:fs");
568368
- const { join: join128, dirname: dirname39 } = await import("node:path");
568369
- const cachePath = join128(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
568370
- mkdirSync67(dirname39(cachePath), { recursive: true });
568371
- writeFileSync59(cachePath, JSON.stringify({
568367
+ const { writeFileSync: writeFileSync60, mkdirSync: mkdirSync68 } = await import("node:fs");
568368
+ const { join: join129, dirname: dirname39 } = await import("node:path");
568369
+ const cachePath = join129(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
568370
+ mkdirSync68(dirname39(cachePath), { recursive: true });
568371
+ writeFileSync60(cachePath, JSON.stringify({
568372
568372
  peerId,
568373
568373
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
568374
568374
  models: models.map((m2) => ({ name: m2.name, size: m2.size, parameterSize: m2.parameterSize }))
@@ -568520,8 +568520,8 @@ ${escapedContent}EOF'`, { timeoutMs: 3e4 });
568520
568520
  }
568521
568521
  await new Promise((r2) => setTimeout(r2, 1e3));
568522
568522
  process.env.OLLAMA_NUM_PARALLEL = String(n2);
568523
- const { spawn: spawn27 } = await import("node:child_process");
568524
- const child = spawn27("ollama", ["serve"], {
568523
+ const { spawn: spawn28 } = await import("node:child_process");
568524
+ const child = spawn28("ollama", ["serve"], {
568525
568525
  stdio: "ignore",
568526
568526
  detached: true,
568527
568527
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n2) }
@@ -568937,17 +568937,17 @@ async function handleUpdate(subcommand, ctx3) {
568937
568937
  try {
568938
568938
  const { createRequire: createRequire8 } = await import("node:module");
568939
568939
  const { fileURLToPath: fileURLToPath20 } = await import("node:url");
568940
- const { dirname: dirname39, join: join128 } = await import("node:path");
568941
- const { existsSync: existsSync110 } = await import("node:fs");
568940
+ const { dirname: dirname39, join: join129 } = await import("node:path");
568941
+ const { existsSync: existsSync111 } = await import("node:fs");
568942
568942
  const req2 = createRequire8(import.meta.url);
568943
568943
  const thisDir = dirname39(fileURLToPath20(import.meta.url));
568944
568944
  const candidates = [
568945
- join128(thisDir, "..", "package.json"),
568946
- join128(thisDir, "..", "..", "package.json"),
568947
- join128(thisDir, "..", "..", "..", "package.json")
568945
+ join129(thisDir, "..", "package.json"),
568946
+ join129(thisDir, "..", "..", "package.json"),
568947
+ join129(thisDir, "..", "..", "..", "package.json")
568948
568948
  ];
568949
568949
  for (const pkgPath of candidates) {
568950
- if (existsSync110(pkgPath)) {
568950
+ if (existsSync111(pkgPath)) {
568951
568951
  const pkg = req2(pkgPath);
568952
568952
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
568953
568953
  currentVersion = pkg.version ?? "0.0.0";
@@ -570095,13 +570095,13 @@ var init_commands = __esm({
570095
570095
  try {
570096
570096
  const { randomBytes: randomBytes25 } = await import("node:crypto");
570097
570097
  const { homedir: homedir46 } = await import("node:os");
570098
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
570099
- const { join: join128 } = await import("node:path");
570098
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
570099
+ const { join: join129 } = await import("node:path");
570100
570100
  const apiKey = randomBytes25(16).toString("hex");
570101
570101
  process.env["OA_API_KEY"] = apiKey;
570102
- const dir = join128(homedir46(), ".open-agents");
570103
- mkdirSync67(dir, { recursive: true });
570104
- writeFileSync59(join128(dir, "api.key"), apiKey + "\n", "utf8");
570102
+ const dir = join129(homedir46(), ".open-agents");
570103
+ mkdirSync68(dir, { recursive: true });
570104
+ writeFileSync60(join129(dir, "api.key"), apiKey + "\n", "utf8");
570105
570105
  renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
570106
570106
  renderInfo2("Use Authorization: Bearer <key> or click 'key' in the Web UI header to paste it.");
570107
570107
  } catch (e2) {
@@ -570116,11 +570116,11 @@ var init_commands = __esm({
570116
570116
  const port = parseInt(process.env["OA_PORT"] || "11435", 10);
570117
570117
  try {
570118
570118
  const { homedir: homedir46 } = await import("node:os");
570119
- const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
570120
- const { join: join128 } = await import("node:path");
570121
- const dir = join128(homedir46(), ".open-agents");
570122
- mkdirSync67(dir, { recursive: true });
570123
- writeFileSync59(join128(dir, "access"), `${val}
570119
+ const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
570120
+ const { join: join129 } = await import("node:path");
570121
+ const dir = join129(homedir46(), ".open-agents");
570122
+ mkdirSync68(dir, { recursive: true });
570123
+ writeFileSync60(join129(dir, "access"), `${val}
570124
570124
  `, "utf8");
570125
570125
  } catch {
570126
570126
  }
@@ -581932,11 +581932,11 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
581932
581932
  let mimeType = "audio/wav";
581933
581933
  try {
581934
581934
  const { execSync: execSyncLocal } = await import("node:child_process");
581935
- const { tmpdir: tmpdir22 } = await import("node:os");
581935
+ const { tmpdir: tmpdir23 } = await import("node:os");
581936
581936
  const { join: joinPath } = await import("node:path");
581937
581937
  const { writeFileSync: writeFs, readFileSync: readFs, unlinkSync: unlinkFs } = await import("node:fs");
581938
- const tmpWav = joinPath(tmpdir22(), `oa-tg-voice-${Date.now()}.wav`);
581939
- const tmpOgg = joinPath(tmpdir22(), `oa-tg-voice-${Date.now()}.ogg`);
581938
+ const tmpWav = joinPath(tmpdir23(), `oa-tg-voice-${Date.now()}.wav`);
581939
+ const tmpOgg = joinPath(tmpdir23(), `oa-tg-voice-${Date.now()}.ogg`);
581940
581940
  writeFs(tmpWav, wavBuffer);
581941
581941
  execSyncLocal(`ffmpeg -i "${tmpWav}" -c:a libopus -b:a 48k -ar 48000 -ac 1 "${tmpOgg}" -y 2>/dev/null`, {
581942
581942
  timeout: 15e3,
@@ -585811,9 +585811,131 @@ var init_tor_fallback = __esm({
585811
585811
  }
585812
585812
  });
585813
585813
 
585814
+ // packages/cli/src/api/graphical-sudo.ts
585815
+ var graphical_sudo_exports = {};
585816
+ __export(graphical_sudo_exports, {
585817
+ detectSudoHelper: () => detectSudoHelper,
585818
+ runGraphicalSudo: () => runGraphicalSudo
585819
+ });
585820
+ import { spawn as spawn24 } from "node:child_process";
585821
+ import { existsSync as existsSync102, mkdirSync as mkdirSync60, writeFileSync as writeFileSync52, chmodSync as chmodSync2 } from "node:fs";
585822
+ import { join as join118 } from "node:path";
585823
+ import { tmpdir as tmpdir21 } from "node:os";
585824
+ function detectSudoHelper() {
585825
+ if (process.platform === "win32") return null;
585826
+ if (process.platform === "darwin") return "osascript";
585827
+ if (which("pkexec")) return "pkexec";
585828
+ if (which("ssh-askpass")) return "ssh-askpass";
585829
+ if (which("zenity")) return "zenity";
585830
+ if (which("kdialog")) return "kdialog";
585831
+ if (which("sudo")) return "sudo-tty";
585832
+ return null;
585833
+ }
585834
+ function which(cmd) {
585835
+ const path8 = process.env["PATH"] || "/usr/bin:/bin:/usr/local/bin";
585836
+ for (const dir of path8.split(":")) {
585837
+ if (!dir) continue;
585838
+ const full = join118(dir, cmd);
585839
+ if (existsSync102(full)) return full;
585840
+ }
585841
+ return null;
585842
+ }
585843
+ function ensureAskpassShim(helper, description) {
585844
+ const shimDir = join118(tmpdir21(), "oa-askpass");
585845
+ mkdirSync60(shimDir, { recursive: true });
585846
+ const shim = join118(shimDir, `${helper}.sh`);
585847
+ let body;
585848
+ if (helper === "zenity") {
585849
+ body = `#!/bin/sh
585850
+ exec zenity --password --title="OA needs sudo" --text="${description.replace(/"/g, '\\"')}" 2>/dev/null
585851
+ `;
585852
+ } else {
585853
+ body = `#!/bin/sh
585854
+ exec kdialog --password "${description.replace(/"/g, '\\"')}" 2>/dev/null
585855
+ `;
585856
+ }
585857
+ writeFileSync52(shim, body, "utf-8");
585858
+ chmodSync2(shim, 493);
585859
+ return shim;
585860
+ }
585861
+ async function runGraphicalSudo(opts) {
585862
+ const helper = detectSudoHelper();
585863
+ const description = opts.description || "Open Agents needs admin access to set up Tor (.onion hidden service)";
585864
+ const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
585865
+ if (!helper) throw new Error("No suitable sudo helper found (pkexec, zenity, kdialog, ssh-askpass).");
585866
+ let cmd;
585867
+ let args;
585868
+ let extraEnv = {};
585869
+ const envFlags = [];
585870
+ for (const [k, v] of Object.entries(opts.env || {})) envFlags.push(`${k}=${v}`);
585871
+ if (helper === "pkexec") {
585872
+ cmd = "pkexec";
585873
+ args = [];
585874
+ if (envFlags.length) args.push(...envFlags.flatMap((e2) => ["--user", "root", "env", e2]));
585875
+ args = ["env", ...envFlags, "/bin/bash", opts.scriptPath, ...opts.args ?? []];
585876
+ } else if (helper === "osascript") {
585877
+ const inner = `${envFlags.map((e2) => `${e2}`).join(" ")} /bin/bash ${shellQuote(opts.scriptPath)} ${shellQuote((opts.args ?? []).join(" "))}`.trim();
585878
+ cmd = "osascript";
585879
+ args = ["-e", `do shell script "${inner.replace(/"/g, '\\"')}" with administrator privileges`];
585880
+ } else if (helper === "ssh-askpass" || helper === "zenity" || helper === "kdialog") {
585881
+ const shim = helper === "ssh-askpass" ? which("ssh-askpass") : ensureAskpassShim(helper, description);
585882
+ extraEnv = { ...extraEnv, SUDO_ASKPASS: shim, DISPLAY: process.env["DISPLAY"] || ":0" };
585883
+ cmd = "sudo";
585884
+ args = ["-A", "-E", "/bin/bash", opts.scriptPath, ...opts.args ?? []];
585885
+ } else {
585886
+ cmd = "sudo";
585887
+ args = ["/bin/bash", opts.scriptPath, ...opts.args ?? []];
585888
+ }
585889
+ return new Promise((resolve43, reject) => {
585890
+ const child = spawn24(cmd, args, {
585891
+ env: { ...process.env, ...opts.env || {}, ...extraEnv },
585892
+ stdio: ["ignore", "pipe", "pipe"]
585893
+ });
585894
+ let stdout = "";
585895
+ let stderr = "";
585896
+ let timedOut = false;
585897
+ const timer = setTimeout(() => {
585898
+ timedOut = true;
585899
+ try {
585900
+ child.kill("SIGTERM");
585901
+ } catch {
585902
+ }
585903
+ setTimeout(() => {
585904
+ try {
585905
+ child.kill("SIGKILL");
585906
+ } catch {
585907
+ }
585908
+ }, 2e3);
585909
+ }, timeoutMs);
585910
+ child.stdout.on("data", (d2) => {
585911
+ stdout += d2.toString("utf-8");
585912
+ });
585913
+ child.stderr.on("data", (d2) => {
585914
+ stderr += d2.toString("utf-8");
585915
+ });
585916
+ child.on("error", (e2) => {
585917
+ clearTimeout(timer);
585918
+ reject(e2);
585919
+ });
585920
+ child.on("close", (code8) => {
585921
+ clearTimeout(timer);
585922
+ if (timedOut) return reject(new Error(`graphical sudo timed out after ${timeoutMs}ms`));
585923
+ resolve43({ code: code8 ?? -1, stdout, stderr, helper });
585924
+ });
585925
+ });
585926
+ }
585927
+ function shellQuote(s2) {
585928
+ return "'" + s2.replace(/'/g, "'\\''") + "'";
585929
+ }
585930
+ var init_graphical_sudo = __esm({
585931
+ "packages/cli/src/api/graphical-sudo.ts"() {
585932
+ "use strict";
585933
+ }
585934
+ });
585935
+
585814
585936
  // packages/cli/src/api/routes-v1.ts
585815
- import { existsSync as existsSync102, readFileSync as readFileSync83, readdirSync as readdirSync34, statSync as statSync34 } from "node:fs";
585816
- import { join as join118, resolve as pathResolve2 } from "node:path";
585937
+ import { existsSync as existsSync103, readFileSync as readFileSync83, readdirSync as readdirSync34, statSync as statSync34 } from "node:fs";
585938
+ import { join as join119, resolve as pathResolve2 } from "node:path";
585817
585939
  import { homedir as homedir40 } from "node:os";
585818
585940
  async function tryRouteV1(ctx3) {
585819
585941
  const { pathname, method } = ctx3;
@@ -585898,6 +586020,9 @@ async function tryRouteV1(ctx3) {
585898
586020
  }
585899
586021
  if (pathname === "/v1/share/generate" && method === "POST") return handleGenerateShare(ctx3);
585900
586022
  if (pathname === "/v1/remote-proxy" && method === "POST") return handleRemoteProxy(ctx3);
586023
+ if (pathname === "/v1/tor/status" && method === "GET") return handleTorStatus(ctx3);
586024
+ if (pathname === "/v1/tor/enable" && method === "POST") return handleTorEnable(ctx3);
586025
+ if (pathname === "/v1/tor/disable" && method === "POST") return handleTorDisable(ctx3);
585901
586026
  if (pathname === "/v1/tools" && method === "GET") {
585902
586027
  return handleListTools(ctx3);
585903
586028
  }
@@ -586044,11 +586169,11 @@ async function handleGetSkill(ctx3, name10) {
586044
586169
  async function fallbackDiscoverSkills() {
586045
586170
  return (_root) => {
586046
586171
  const roots = [
586047
- join118(homedir40(), ".local", "share", "ai-writing-guide")
586172
+ join119(homedir40(), ".local", "share", "ai-writing-guide")
586048
586173
  ];
586049
586174
  const out = [];
586050
586175
  for (const root of roots) {
586051
- if (!existsSync102(root)) continue;
586176
+ if (!existsSync103(root)) continue;
586052
586177
  walkForSkills(root, out, 0);
586053
586178
  }
586054
586179
  return out;
@@ -586059,7 +586184,7 @@ function walkForSkills(dir, out, depth) {
586059
586184
  try {
586060
586185
  for (const e2 of readdirSync34(dir, { withFileTypes: true })) {
586061
586186
  if (e2.name.startsWith(".") || e2.name === "node_modules") continue;
586062
- const p2 = join118(dir, e2.name);
586187
+ const p2 = join119(dir, e2.name);
586063
586188
  if (e2.isDirectory()) {
586064
586189
  walkForSkills(p2, out, depth + 1);
586065
586190
  } else if (e2.isFile() && e2.name === "SKILL.md") {
@@ -586248,7 +586373,7 @@ async function getMemoryStores() {
586248
586373
  if (memoryInitTried) return null;
586249
586374
  memoryInitTried = true;
586250
586375
  try {
586251
- const dbPath = join118(homedir40(), ".open-agents", "memory.db");
586376
+ const dbPath = join119(homedir40(), ".open-agents", "memory.db");
586252
586377
  const sharedDb = initDb(dbPath);
586253
586378
  memoryStoresCache = {
586254
586379
  episode: new EpisodeStore(dbPath),
@@ -586506,7 +586631,7 @@ async function handleFilesRead(ctx3) {
586506
586631
  }));
586507
586632
  return true;
586508
586633
  }
586509
- if (!existsSync102(resolved)) {
586634
+ if (!existsSync103(resolved)) {
586510
586635
  sendProblem(res, problemDetails({
586511
586636
  type: P.notFound,
586512
586637
  status: 404,
@@ -586771,12 +586896,12 @@ async function handleNexusStatus(ctx3) {
586771
586896
  const { res, requestId } = ctx3;
586772
586897
  try {
586773
586898
  const statePaths = [
586774
- join118(process.cwd(), ".oa", "nexus-peer-state.json"),
586775
- join118(homedir40(), ".open-agents", "nexus-peer-cache.json")
586899
+ join119(process.cwd(), ".oa", "nexus-peer-state.json"),
586900
+ join119(homedir40(), ".open-agents", "nexus-peer-cache.json")
586776
586901
  ];
586777
586902
  const states = [];
586778
586903
  for (const p2 of statePaths) {
586779
- if (!existsSync102(p2)) continue;
586904
+ if (!existsSync103(p2)) continue;
586780
586905
  try {
586781
586906
  const raw = readFileSync83(p2, "utf-8");
586782
586907
  states.push({ source: p2, data: JSON.parse(raw) });
@@ -586805,8 +586930,8 @@ async function handleNexusStatus(ctx3) {
586805
586930
  }
586806
586931
  function loadAgentName() {
586807
586932
  try {
586808
- const p2 = join118(homedir40(), ".open-agents", "agent-name");
586809
- if (existsSync102(p2)) return readFileSync83(p2, "utf-8").trim();
586933
+ const p2 = join119(homedir40(), ".open-agents", "agent-name");
586934
+ if (existsSync103(p2)) return readFileSync83(p2, "utf-8").trim();
586810
586935
  } catch {
586811
586936
  }
586812
586937
  return null;
@@ -586815,12 +586940,12 @@ async function handleSponsors(ctx3) {
586815
586940
  const { req: req2, res, url, requestId } = ctx3;
586816
586941
  try {
586817
586942
  const candidates = [
586818
- join118(homedir40(), ".open-agents", "sponsor-cache.json"),
586819
- join118(homedir40(), ".open-agents", "sponsors.json")
586943
+ join119(homedir40(), ".open-agents", "sponsor-cache.json"),
586944
+ join119(homedir40(), ".open-agents", "sponsors.json")
586820
586945
  ];
586821
586946
  let sponsors = [];
586822
586947
  for (const p2 of candidates) {
586823
- if (!existsSync102(p2)) continue;
586948
+ if (!existsSync103(p2)) continue;
586824
586949
  try {
586825
586950
  const raw = JSON.parse(readFileSync83(p2, "utf-8"));
586826
586951
  if (Array.isArray(raw)) {
@@ -586891,8 +587016,8 @@ async function handleEvaluate(ctx3) {
586891
587016
  }));
586892
587017
  return true;
586893
587018
  }
586894
- const jobPath = join118(process.cwd(), ".oa", "jobs", `${runId}.json`);
586895
- if (!existsSync102(jobPath)) {
587019
+ const jobPath = join119(process.cwd(), ".oa", "jobs", `${runId}.json`);
587020
+ if (!existsSync103(jobPath)) {
586896
587021
  sendProblem(res, problemDetails({
586897
587022
  type: P.notFound,
586898
587023
  status: 404,
@@ -587040,7 +587165,7 @@ async function handleMintKey(ctx3) {
587040
587165
  return true;
587041
587166
  }
587042
587167
  function _readStatusFile(p2) {
587043
- if (!existsSync102(p2)) return null;
587168
+ if (!existsSync103(p2)) return null;
587044
587169
  try {
587045
587170
  const data = JSON.parse(readFileSync83(p2, "utf-8"));
587046
587171
  if (data?.connected && typeof data.peerId === "string" && data.peerId.length > 10) {
@@ -587057,18 +587182,18 @@ function _readStatusFile(p2) {
587057
587182
  function resolveLocalPeerId() {
587058
587183
  const override = process.env["OA_NEXUS_DIR"];
587059
587184
  if (override) {
587060
- const r2 = _readStatusFile(join118(override, "status.json"));
587185
+ const r2 = _readStatusFile(join119(override, "status.json"));
587061
587186
  if (r2) return r2;
587062
587187
  }
587063
587188
  try {
587064
- const regPath = join118(homedir40(), ".open-agents", "nexus-registry.json");
587065
- if (existsSync102(regPath)) {
587189
+ const regPath = join119(homedir40(), ".open-agents", "nexus-registry.json");
587190
+ if (existsSync103(regPath)) {
587066
587191
  const reg = JSON.parse(readFileSync83(regPath, "utf-8"));
587067
587192
  const entries = Array.isArray(reg?.dirs) ? reg.dirs : [];
587068
587193
  for (const entry of entries) {
587069
587194
  const dir = typeof entry === "string" ? entry : entry?.dir;
587070
587195
  if (typeof dir === "string") {
587071
- const r2 = _readStatusFile(join118(dir, "status.json"));
587196
+ const r2 = _readStatusFile(join119(dir, "status.json"));
587072
587197
  if (r2) return r2;
587073
587198
  }
587074
587199
  }
@@ -587076,9 +587201,9 @@ function resolveLocalPeerId() {
587076
587201
  } catch {
587077
587202
  }
587078
587203
  const candidates = [
587079
- join118(process.cwd(), ".oa", "nexus", "status.json"),
587080
- join118(homedir40(), ".oa", "nexus", "status.json"),
587081
- join118(homedir40(), ".open-agents", "nexus", "status.json")
587204
+ join119(process.cwd(), ".oa", "nexus", "status.json"),
587205
+ join119(homedir40(), ".oa", "nexus", "status.json"),
587206
+ join119(homedir40(), ".open-agents", "nexus", "status.json")
587082
587207
  ];
587083
587208
  for (const p2 of candidates) {
587084
587209
  const r2 = _readStatusFile(p2);
@@ -587107,6 +587232,144 @@ function resolveLocalPeerId() {
587107
587232
  _peerIdScanCache = { ts: now, result: scanResult };
587108
587233
  return scanResult;
587109
587234
  }
587235
+ async function handleTorStatus(ctx3) {
587236
+ const { res } = ctx3;
587237
+ const { getLocalOnion: getLocalOnion2, torIsReachable: torIsReachable2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
587238
+ const { detectSudoHelper: detectSudoHelper2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587239
+ const onion = getLocalOnion2();
587240
+ const reachable = await torIsReachable2();
587241
+ sendJson(res, 200, {
587242
+ onion,
587243
+ socks5_reachable: reachable,
587244
+ sudo_helper: detectSudoHelper2()
587245
+ });
587246
+ return true;
587247
+ }
587248
+ async function handleTorEnable(ctx3) {
587249
+ const { req: req2, res, requestId } = ctx3;
587250
+ const reqAuth = req2;
587251
+ if (reqAuth._authScope !== "admin") {
587252
+ sendProblem(res, problemDetails({
587253
+ type: P.forbidden,
587254
+ status: 403,
587255
+ title: "Admin scope required",
587256
+ detail: "Tor setup requires elevated privileges; only admin keys can request it.",
587257
+ instance: requestId
587258
+ }));
587259
+ return true;
587260
+ }
587261
+ const { getLocalOnion: getLocalOnion2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
587262
+ if (getLocalOnion2()) {
587263
+ sendJson(res, 409, {
587264
+ status: "already_configured",
587265
+ onion: getLocalOnion2(),
587266
+ _note: "Tor hidden service already exists. Use /v1/tor/disable to remove."
587267
+ });
587268
+ return true;
587269
+ }
587270
+ let scriptPath2 = null;
587271
+ try {
587272
+ const candidates = [
587273
+ join119(process.cwd(), "scripts", "tor", "tor_setup.sh"),
587274
+ join119(__dirname, "..", "..", "scripts", "tor", "tor_setup.sh"),
587275
+ join119(__dirname, "..", "scripts", "tor", "tor_setup.sh")
587276
+ ];
587277
+ for (const p2 of candidates) {
587278
+ if (existsSync103(p2)) {
587279
+ scriptPath2 = p2;
587280
+ break;
587281
+ }
587282
+ }
587283
+ if (!scriptPath2) {
587284
+ const { execSync: execSync59 } = __require("node:child_process");
587285
+ const root = execSync59("npm root -g", { encoding: "utf-8", timeout: 5e3 }).trim();
587286
+ const p2 = join119(root, "open-agents-ai", "scripts", "tor", "tor_setup.sh");
587287
+ if (existsSync103(p2)) scriptPath2 = p2;
587288
+ }
587289
+ } catch {
587290
+ }
587291
+ if (!scriptPath2) {
587292
+ sendProblem(res, problemDetails({
587293
+ type: P.internalError,
587294
+ status: 500,
587295
+ title: "tor_setup.sh not found",
587296
+ detail: "Could not locate the bundled Tor setup script.",
587297
+ instance: requestId
587298
+ }));
587299
+ return true;
587300
+ }
587301
+ const { detectSudoHelper: detectSudoHelper2, runGraphicalSudo: runGraphicalSudo2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587302
+ const helper = detectSudoHelper2();
587303
+ if (!helper) {
587304
+ sendProblem(res, problemDetails({
587305
+ type: P.internalError,
587306
+ status: 503,
587307
+ title: "No graphical sudo helper",
587308
+ detail: "Install one of: pkexec (PolKit), zenity, kdialog, or ssh-askpass — then retry.",
587309
+ instance: requestId
587310
+ }));
587311
+ return true;
587312
+ }
587313
+ sendJson(res, 202, {
587314
+ status: "accepted",
587315
+ helper,
587316
+ script: scriptPath2,
587317
+ poll: "/v1/tor/status"
587318
+ });
587319
+ const apiPort = req2.socket?.localPort || parseInt(process.env["OA_API_PORT"] || "11435", 10);
587320
+ runGraphicalSudo2({
587321
+ scriptPath: scriptPath2,
587322
+ env: { OA_API_PORT: String(apiPort) },
587323
+ description: "Open Agents needs admin access to install Tor and configure a hidden service"
587324
+ }).then((r2) => {
587325
+ if (r2.code !== 0) {
587326
+ console.warn(`[tor-enable] sudo helper ${r2.helper} exited ${r2.code}: ${r2.stderr.slice(-300)}`);
587327
+ }
587328
+ }).catch((e2) => {
587329
+ console.warn(`[tor-enable] failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
587330
+ });
587331
+ return true;
587332
+ }
587333
+ async function handleTorDisable(ctx3) {
587334
+ const { req: req2, res, requestId } = ctx3;
587335
+ const reqAuth = req2;
587336
+ if (reqAuth._authScope !== "admin") {
587337
+ sendProblem(res, problemDetails({
587338
+ type: P.forbidden,
587339
+ status: 403,
587340
+ title: "Admin scope required",
587341
+ detail: "Tor teardown requires admin scope.",
587342
+ instance: requestId
587343
+ }));
587344
+ return true;
587345
+ }
587346
+ let scriptPath2 = null;
587347
+ const candidates = [
587348
+ join119(process.cwd(), "scripts", "tor", "destroy_tor.sh"),
587349
+ join119(__dirname, "..", "..", "scripts", "tor", "destroy_tor.sh"),
587350
+ join119(__dirname, "..", "scripts", "tor", "destroy_tor.sh")
587351
+ ];
587352
+ for (const p2 of candidates) {
587353
+ if (existsSync103(p2)) {
587354
+ scriptPath2 = p2;
587355
+ break;
587356
+ }
587357
+ }
587358
+ if (!scriptPath2) {
587359
+ sendProblem(res, problemDetails({
587360
+ type: P.internalError,
587361
+ status: 500,
587362
+ title: "destroy_tor.sh not found",
587363
+ detail: "Bundled teardown script missing.",
587364
+ instance: requestId
587365
+ }));
587366
+ return true;
587367
+ }
587368
+ const { runGraphicalSudo: runGraphicalSudo2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587369
+ sendJson(res, 202, { status: "accepted", script: scriptPath2 });
587370
+ runGraphicalSudo2({ scriptPath: scriptPath2, description: "Open Agents needs admin access to remove the Tor hidden service" }).catch((e2) => console.warn(`[tor-disable] failed: ${e2 instanceof Error ? e2.message : String(e2)}`));
587371
+ return true;
587372
+ }
587110
587373
  async function handleGenerateShare(ctx3) {
587111
587374
  const { req: req2, res, requestId } = ctx3;
587112
587375
  const reqAuth = req2;
@@ -587174,9 +587437,11 @@ async function handleGenerateShare(ctx3) {
587174
587437
  if (onion) plainParams.push(`oa-onion=${encodeURIComponent(onion)}`);
587175
587438
  plainParams.push(`oa-share-label=${encodeURIComponent(label)}`);
587176
587439
  const plainUrl = `${scheme}://${hostPort}/?${plainParams.join("&")}`;
587440
+ const torShareUrl = onion ? `oa-share-tor://${onion}#${fullKey}` : null;
587177
587441
  sendJson(res, 201, {
587178
587442
  shareUrl,
587179
587443
  plainUrl,
587444
+ torShareUrl,
587180
587445
  mode,
587181
587446
  peerId: peerInfo?.peerId || null,
587182
587447
  onion: onion || null,
@@ -587192,7 +587457,7 @@ async function handleGenerateShare(ctx3) {
587192
587457
  tor: !!onion,
587193
587458
  direct: !peerInfo
587194
587459
  },
587195
- _note: peerInfo && onion ? "Globally reachable via libp2p (primary) and Tor (.onion fallback)." : peerInfo ? "Globally reachable via libp2p. For maximum reach add Tor: see scripts/tor/tor_setup.sh." : "Nexus daemon offline — URL is direct-HTTP only (LAN/VPN reach). Start nexus for global reach."
587460
+ _note: peerInfo && onion ? "Globally reachable via libp2p (primary) and Tor (.onion fallback)." : peerInfo ? "Globally reachable via libp2p. For maximum reach add Tor: run `oa tor enable`." : onion ? "Globally reachable via Tor only (.onion). Start nexus for libp2p tier." : "Nexus offline + no Tor — URL is direct-HTTP only (LAN/VPN reach)."
587196
587461
  });
587197
587462
  } catch (err) {
587198
587463
  sendProblem(res, problemDetails({
@@ -587250,13 +587515,13 @@ async function handleRemoteProxy(ctx3) {
587250
587515
  return true;
587251
587516
  }
587252
587517
  const nexusCandidates = [
587253
- join118(process.cwd(), ".oa", "nexus"),
587254
- join118(homedir40(), ".oa", "nexus"),
587255
- join118(homedir40(), ".open-agents", "nexus")
587518
+ join119(process.cwd(), ".oa", "nexus"),
587519
+ join119(homedir40(), ".oa", "nexus"),
587520
+ join119(homedir40(), ".open-agents", "nexus")
587256
587521
  ];
587257
587522
  let nexusDirPath = null;
587258
587523
  for (const p2 of nexusCandidates) {
587259
- if (existsSync102(join118(p2, "status.json"))) {
587524
+ if (existsSync103(join119(p2, "status.json"))) {
587260
587525
  nexusDirPath = p2;
587261
587526
  break;
587262
587527
  }
@@ -587352,7 +587617,7 @@ async function handleRemoteProxy(ctx3) {
587352
587617
  }));
587353
587618
  return true;
587354
587619
  }
587355
- const streamFile = join118(nexusDirPath, `tunnel-${requestId}-${Date.now()}.jsonl`);
587620
+ const streamFile = join119(nexusDirPath, `tunnel-${requestId}-${Date.now()}.jsonl`);
587356
587621
  try {
587357
587622
  const { writeFileSync: _wfs } = await import("node:fs");
587358
587623
  _wfs(streamFile, "");
@@ -587795,14 +588060,14 @@ async function handleListEngines(ctx3) {
587795
588060
  const home = homedir40();
587796
588061
  sendJson(res, 200, {
587797
588062
  engines: [
587798
- { name: "dream", state_file: join118(process.cwd(), ".oa", "dreams"), controllable_via: "SSE + slash commands" },
587799
- { name: "bless", state_file: join118(process.cwd(), ".oa", "bless-state.json"), controllable_via: "slash commands" },
587800
- { name: "call", state_file: join118(process.cwd(), ".oa", "call-state.json"), controllable_via: "slash commands" },
587801
- { name: "listen", state_file: join118(process.cwd(), ".oa", "listen-state.json"), controllable_via: "slash commands" },
587802
- { name: "telegram", state_file: join118(home, ".open-agents", "telegram-state.json"), controllable_via: "slash commands" },
587803
- { name: "expose", state_file: join118(process.cwd(), ".oa", "expose-state.json"), controllable_via: "/expose commands" },
587804
- { name: "nexus", state_file: join118(home, ".open-agents", "nexus-peer-cache.json"), controllable_via: "/nexus commands" },
587805
- { name: "ipfs", state_file: join118(process.cwd(), ".oa", "ipfs"), controllable_via: "slash commands" }
588063
+ { name: "dream", state_file: join119(process.cwd(), ".oa", "dreams"), controllable_via: "SSE + slash commands" },
588064
+ { name: "bless", state_file: join119(process.cwd(), ".oa", "bless-state.json"), controllable_via: "slash commands" },
588065
+ { name: "call", state_file: join119(process.cwd(), ".oa", "call-state.json"), controllable_via: "slash commands" },
588066
+ { name: "listen", state_file: join119(process.cwd(), ".oa", "listen-state.json"), controllable_via: "slash commands" },
588067
+ { name: "telegram", state_file: join119(home, ".open-agents", "telegram-state.json"), controllable_via: "slash commands" },
588068
+ { name: "expose", state_file: join119(process.cwd(), ".oa", "expose-state.json"), controllable_via: "/expose commands" },
588069
+ { name: "nexus", state_file: join119(home, ".open-agents", "nexus-peer-cache.json"), controllable_via: "/nexus commands" },
588070
+ { name: "ipfs", state_file: join119(process.cwd(), ".oa", "ipfs"), controllable_via: "slash commands" }
587806
588071
  ],
587807
588072
  note: "Engine instrumentation lives in the running TUI process. Full status + control requires the daemon↔TUI bridge (PT-07). See parity audit WO-PARITY-04."
587808
588073
  });
@@ -587885,21 +588150,21 @@ async function tryAimsRoute(ctx3) {
587885
588150
  return false;
587886
588151
  }
587887
588152
  function aimsDir() {
587888
- return join118(homedir40(), ".open-agents", "aims");
588153
+ return join119(homedir40(), ".open-agents", "aims");
587889
588154
  }
587890
588155
  function readAimsFile(name10, fallback) {
587891
588156
  try {
587892
- const p2 = join118(aimsDir(), name10);
587893
- if (existsSync102(p2)) return JSON.parse(readFileSync83(p2, "utf-8"));
588157
+ const p2 = join119(aimsDir(), name10);
588158
+ if (existsSync103(p2)) return JSON.parse(readFileSync83(p2, "utf-8"));
587894
588159
  } catch {
587895
588160
  }
587896
588161
  return fallback;
587897
588162
  }
587898
588163
  function writeAimsFile(name10, data) {
587899
588164
  const dir = aimsDir();
587900
- const { mkdirSync: mkdirSync67, writeFileSync: wf, renameSync: rn } = __require("node:fs");
587901
- mkdirSync67(dir, { recursive: true });
587902
- const finalPath = join118(dir, name10);
588165
+ const { mkdirSync: mkdirSync68, writeFileSync: wf, renameSync: rn } = __require("node:fs");
588166
+ mkdirSync68(dir, { recursive: true });
588167
+ const finalPath = join119(dir, name10);
587903
588168
  const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
587904
588169
  try {
587905
588170
  wf(tmpPath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
@@ -588229,10 +588494,10 @@ async function handleAimsSuppliers(ctx3) {
588229
588494
  }
588230
588495
  ];
588231
588496
  const sponsorPaths = [
588232
- join118(homedir40(), ".open-agents", "sponsor-cache.json")
588497
+ join119(homedir40(), ".open-agents", "sponsor-cache.json")
588233
588498
  ];
588234
588499
  for (const p2 of sponsorPaths) {
588235
- if (!existsSync102(p2)) continue;
588500
+ if (!existsSync103(p2)) continue;
588236
588501
  try {
588237
588502
  const raw = JSON.parse(readFileSync83(p2, "utf-8"));
588238
588503
  const list = Array.isArray(raw) ? raw : raw?.sponsors ?? [];
@@ -591759,6 +592024,19 @@ function _looksLikePeerId(s) {
591759
592024
  function parseShareInput(raw) {
591760
592025
  const v = String(raw || '').trim();
591761
592026
  if (!v) return null;
592027
+ // oa-share-tor scheme — Tor-only routing via SOCKS5 to <onion>:80
592028
+ if (v.toLowerCase().startsWith('oa-share-tor://')) {
592029
+ const after = v.slice('oa-share-tor://'.length);
592030
+ const hashIdx = after.indexOf('#');
592031
+ if (hashIdx < 0) return null;
592032
+ const onionRaw = after.slice(0, hashIdx);
592033
+ // Strip optional :port suffix; we always dial 80 since hidden services
592034
+ // are configured to forward 80 → local API per the leek_messenger setup.
592035
+ const onion = onionRaw.split(':')[0];
592036
+ const key = after.slice(hashIdx + 1);
592037
+ if (!onion.endsWith('.onion') || !key) return null;
592038
+ return { peerId: null, onion, host: null, key, scheme: 'tor' };
592039
+ }
591762
592040
  // oa-share scheme — custom parser since URL() doesn't always honor it.
591763
592041
  if (v.toLowerCase().startsWith('oa-share://')) {
591764
592042
  const after = v.slice('oa-share://'.length);
@@ -591919,10 +592197,25 @@ async function generateShareUrl() {
591919
592197
  const j = await r.json();
591920
592198
  const safeShare = escapeHtml(j.shareUrl || '');
591921
592199
  const safePlain = escapeHtml(j.plainUrl || '');
592200
+ const safeTor = escapeHtml(j.torShareUrl || '');
592201
+ const torRow = j.torShareUrl
592202
+ ? '<div style="margin:6px 0">' +
592203
+ '<label style="display:block;font-size:0.7rem;color:var(--color-fg-muted);margin-bottom:2px">tor-only URL (.onion routed via SOCKS5 — works through any firewall)</label>' +
592204
+ '<div style="display:flex;gap:6px;align-items:center">' +
592205
+ '<input readonly value="' + safeTor + '" style="flex:1;background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-fg);padding:5px 8px;border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:0.74rem">' +
592206
+ '<button type="button" onclick="copyShareUrl(\\'tor\\')" style="font-size:0.74rem">copy</button>' +
592207
+ '</div>' +
592208
+ '</div>'
592209
+ : '<div style="margin:8px 0;padding:8px;background:var(--color-bg-input);border:1px dashed var(--color-border);border-radius:var(--radius-sm)">' +
592210
+ '<div style="font-size:0.74rem;margin-bottom:4px">Tor (.onion) is not configured on this OA.</div>' +
592211
+ '<div style="font-size:0.68rem;color:var(--color-fg-muted);margin-bottom:6px">Enable Tor for global reach when libp2p fails. Asks for sudo via your system password dialog.</div>' +
592212
+ '<button type="button" onclick="enableTorShare()" style="font-size:0.74rem;background:var(--color-accent);color:#fff;border:none;padding:4px 12px;border-radius:var(--radius-sm);cursor:pointer">enable Tor</button>' +
592213
+ '<span id="enable-tor-status" style="font-size:0.68rem;margin-left:8px;color:var(--color-fg-muted)"></span>' +
592214
+ '</div>';
591922
592215
  out.innerHTML =
591923
592216
  '<div style="font-weight:500;margin-bottom:6px;color:var(--color-success)">✓ Share URL generated — hand off to remote</div>' +
591924
592217
  '<div style="margin:6px 0">' +
591925
- '<label style="display:block;font-size:0.7rem;color:var(--color-fg-muted);margin-bottom:2px">oa-share URL (compact, recommended for OA-to-OA)</label>' +
592218
+ '<label style="display:block;font-size:0.7rem;color:var(--color-fg-muted);margin-bottom:2px">oa-share URL (libp2p, compact, recommended for OA-to-OA)</label>' +
591926
592219
  '<div style="display:flex;gap:6px;align-items:center">' +
591927
592220
  '<input readonly value="' + safeShare + '" style="flex:1;background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-fg);padding:5px 8px;border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:0.74rem">' +
591928
592221
  '<button type="button" onclick="copyShareUrl(\\'oa-share\\')" style="font-size:0.74rem">copy</button>' +
@@ -591935,17 +592228,22 @@ async function generateShareUrl() {
591935
592228
  '<button type="button" onclick="copyShareUrl(\\'plain\\')" style="font-size:0.74rem">copy</button>' +
591936
592229
  '</div>' +
591937
592230
  '</div>' +
591938
- '<p style="font-size:0.68rem;color:var(--color-fg-muted);margin:6px 0 0">Note: this URL contains the full secret. Anyone with it can use this OA. To revoke: open Advanced settings → keys → revoke the prefix <code>' + escapeHtml(j.keyPrefix || '') + '</code>.</p>';
592231
+ torRow +
592232
+ '<p style="font-size:0.68rem;color:var(--color-fg-muted);margin:6px 0 0">Note: these URLs contain the full secret. Anyone with one can use this OA. To revoke: Advanced settings → keys → revoke prefix <code>' + escapeHtml(j.keyPrefix || '') + '</code>.</p>';
591939
592233
  // Stash for the copy buttons + add to recent.
591940
592234
  window.__oaLastShareUrl = j.shareUrl;
591941
592235
  window.__oaLastPlainUrl = j.plainUrl;
592236
+ window.__oaLastTorUrl = j.torShareUrl || null;
591942
592237
  saveRecentKey({ key: j.key, host: j.host + ':' + j.port, label: j.label || ('shared ' + j.host) });
591943
592238
  } catch (e) {
591944
592239
  out.innerHTML = '<div style="color:var(--color-error)">✗ ' + escapeHtml(e && e.message ? e.message : String(e)) + '</div>';
591945
592240
  }
591946
592241
  }
591947
592242
  function copyShareUrl(which) {
591948
- const v = which === 'plain' ? window.__oaLastPlainUrl : window.__oaLastShareUrl;
592243
+ let v;
592244
+ if (which === 'plain') v = window.__oaLastPlainUrl;
592245
+ else if (which === 'tor') v = window.__oaLastTorUrl;
592246
+ else v = window.__oaLastShareUrl;
591949
592247
  if (!v) return;
591950
592248
  if (navigator.clipboard && navigator.clipboard.writeText) {
591951
592249
  navigator.clipboard.writeText(v).then(
@@ -591965,6 +592263,46 @@ function fallbackCopy(v) {
591965
592263
  window.generateShareUrl = generateShareUrl;
591966
592264
  window.copyShareUrl = copyShareUrl;
591967
592265
 
592266
+ // ─── Enable Tor (graphical sudo) ────────────────────────────────────────
592267
+ async function enableTorShare() {
592268
+ const status = document.getElementById('enable-tor-status');
592269
+ if (status) { status.textContent = 'launching graphical sudo prompt…'; status.style.color = 'var(--color-fg-muted)'; }
592270
+ try {
592271
+ const r = await fetch('/v1/tor/enable', {
592272
+ method: 'POST',
592273
+ headers: { ...headers(), 'Content-Type': 'application/json' },
592274
+ body: '{}',
592275
+ });
592276
+ const j = await r.json().catch(() => ({}));
592277
+ if (r.status === 202) {
592278
+ if (status) {
592279
+ status.textContent = 'started — waiting for hidden service…';
592280
+ status.style.color = 'var(--color-accent)';
592281
+ }
592282
+ // Poll up to 90s for the .onion to appear
592283
+ for (let i = 0; i < 30; i++) {
592284
+ await new Promise(r => setTimeout(r, 3000));
592285
+ const s = await fetch('/v1/tor/status', { headers: headers() }).then(x => x.json()).catch(() => ({}));
592286
+ if (s.onion) {
592287
+ if (status) { status.textContent = '✓ Tor enabled: ' + s.onion; status.style.color = 'var(--color-success)'; }
592288
+ // Re-generate share URL to pick up the .onion field
592289
+ setTimeout(() => generateShareUrl(), 500);
592290
+ return;
592291
+ }
592292
+ }
592293
+ if (status) { status.textContent = '⚠ setup ran but no .onion appeared. Check journalctl -u tor for errors.'; status.style.color = 'var(--color-warning)'; }
592294
+ } else if (r.status === 409) {
592295
+ if (status) { status.textContent = '✓ already enabled — re-generating'; status.style.color = 'var(--color-success)'; }
592296
+ setTimeout(() => generateShareUrl(), 500);
592297
+ } else {
592298
+ if (status) { status.textContent = '✗ ' + (j.detail || ('HTTP ' + r.status)); status.style.color = 'var(--color-error)'; }
592299
+ }
592300
+ } catch (e) {
592301
+ if (status) { status.textContent = '✗ ' + (e && e.message ? e.message : String(e)); status.style.color = 'var(--color-error)'; }
592302
+ }
592303
+ }
592304
+ window.enableTorShare = enableTorShare;
592305
+
591968
592306
  // ─── Remote-state helpers (visual indicator on the key button) ───────
591969
592307
  // When localStorage carries oa.remoteHost we are in REMOTE mode: the
591970
592308
  // key was loaded from an oa-share URL or via on-load ?oa-key=. The key
@@ -596842,14 +597180,14 @@ var init_auth_oidc = __esm({
596842
597180
  });
596843
597181
 
596844
597182
  // packages/cli/src/api/usage-tracker.ts
596845
- import { mkdirSync as mkdirSync60, readFileSync as readFileSync84, writeFileSync as writeFileSync52, existsSync as existsSync103 } from "node:fs";
596846
- import { join as join119 } from "node:path";
597183
+ import { mkdirSync as mkdirSync61, readFileSync as readFileSync84, writeFileSync as writeFileSync53, existsSync as existsSync104 } from "node:fs";
597184
+ import { join as join120 } from "node:path";
596847
597185
  function initUsageTracker(oaDir) {
596848
- const dir = join119(oaDir, "usage");
596849
- mkdirSync60(dir, { recursive: true });
596850
- usageFile = join119(dir, "token-usage.json");
597186
+ const dir = join120(oaDir, "usage");
597187
+ mkdirSync61(dir, { recursive: true });
597188
+ usageFile = join120(dir, "token-usage.json");
596851
597189
  try {
596852
- if (existsSync103(usageFile)) {
597190
+ if (existsSync104(usageFile)) {
596853
597191
  store = JSON.parse(readFileSync84(usageFile, "utf-8"));
596854
597192
  }
596855
597193
  } catch {
@@ -596886,7 +597224,7 @@ function flush2() {
596886
597224
  if (!initialized2 || !dirty) return;
596887
597225
  try {
596888
597226
  store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
596889
- writeFileSync52(usageFile, JSON.stringify(store, null, 2), "utf-8");
597227
+ writeFileSync53(usageFile, JSON.stringify(store, null, 2), "utf-8");
596890
597228
  dirty = false;
596891
597229
  } catch {
596892
597230
  }
@@ -596914,24 +597252,24 @@ var init_usage_tracker = __esm({
596914
597252
  });
596915
597253
 
596916
597254
  // packages/cli/src/api/profiles.ts
596917
- import { existsSync as existsSync104, readFileSync as readFileSync85, writeFileSync as writeFileSync53, mkdirSync as mkdirSync61, readdirSync as readdirSync35, unlinkSync as unlinkSync23 } from "node:fs";
596918
- import { join as join120 } from "node:path";
597255
+ import { existsSync as existsSync105, readFileSync as readFileSync85, writeFileSync as writeFileSync54, mkdirSync as mkdirSync62, readdirSync as readdirSync35, unlinkSync as unlinkSync23 } from "node:fs";
597256
+ import { join as join121 } from "node:path";
596919
597257
  import { homedir as homedir41 } from "node:os";
596920
597258
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes22, scryptSync as scryptSync3 } from "node:crypto";
596921
597259
  function globalProfileDir() {
596922
- return join120(homedir41(), ".open-agents", "profiles");
597260
+ return join121(homedir41(), ".open-agents", "profiles");
596923
597261
  }
596924
597262
  function projectProfileDir(projectDir2) {
596925
- return join120(projectDir2 || process.cwd(), ".oa", "profiles");
597263
+ return join121(projectDir2 || process.cwd(), ".oa", "profiles");
596926
597264
  }
596927
597265
  function listProfiles(projectDir2) {
596928
597266
  const result = [];
596929
597267
  const seen = /* @__PURE__ */ new Set();
596930
597268
  const projDir = projectProfileDir(projectDir2);
596931
- if (existsSync104(projDir)) {
597269
+ if (existsSync105(projDir)) {
596932
597270
  for (const f2 of readdirSync35(projDir).filter((f3) => f3.endsWith(".json"))) {
596933
597271
  try {
596934
- const raw = JSON.parse(readFileSync85(join120(projDir, f2), "utf8"));
597272
+ const raw = JSON.parse(readFileSync85(join121(projDir, f2), "utf8"));
596935
597273
  const name10 = f2.replace(".json", "");
596936
597274
  seen.add(name10);
596937
597275
  result.push({
@@ -596945,12 +597283,12 @@ function listProfiles(projectDir2) {
596945
597283
  }
596946
597284
  }
596947
597285
  const globDir = globalProfileDir();
596948
- if (existsSync104(globDir)) {
597286
+ if (existsSync105(globDir)) {
596949
597287
  for (const f2 of readdirSync35(globDir).filter((f3) => f3.endsWith(".json"))) {
596950
597288
  const name10 = f2.replace(".json", "");
596951
597289
  if (seen.has(name10)) continue;
596952
597290
  try {
596953
- const raw = JSON.parse(readFileSync85(join120(globDir, f2), "utf8"));
597291
+ const raw = JSON.parse(readFileSync85(join121(globDir, f2), "utf8"));
596954
597292
  result.push({
596955
597293
  name: name10,
596956
597294
  description: raw.description || "",
@@ -596965,9 +597303,9 @@ function listProfiles(projectDir2) {
596965
597303
  }
596966
597304
  function loadProfile(name10, password, projectDir2) {
596967
597305
  const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
596968
- const projPath = join120(projectProfileDir(projectDir2), `${sanitized}.json`);
596969
- const globPath = join120(globalProfileDir(), `${sanitized}.json`);
596970
- const filePath = existsSync104(projPath) ? projPath : existsSync104(globPath) ? globPath : null;
597306
+ const projPath = join121(projectProfileDir(projectDir2), `${sanitized}.json`);
597307
+ const globPath = join121(globalProfileDir(), `${sanitized}.json`);
597308
+ const filePath = existsSync105(projPath) ? projPath : existsSync105(globPath) ? globPath : null;
596971
597309
  if (!filePath) return null;
596972
597310
  const raw = JSON.parse(readFileSync85(filePath, "utf8"));
596973
597311
  if (raw.encrypted === true) {
@@ -596978,23 +597316,23 @@ function loadProfile(name10, password, projectDir2) {
596978
597316
  }
596979
597317
  function saveProfile(profile, password, scope = "global", projectDir2) {
596980
597318
  const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
596981
- mkdirSync61(dir, { recursive: true });
597319
+ mkdirSync62(dir, { recursive: true });
596982
597320
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
596983
- const filePath = join120(dir, `${sanitized}.json`);
597321
+ const filePath = join121(dir, `${sanitized}.json`);
596984
597322
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
596985
597323
  if (password) {
596986
597324
  const encrypted = encryptProfile(profile, password);
596987
- writeFileSync53(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
597325
+ writeFileSync54(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
596988
597326
  } else {
596989
597327
  profile.encrypted = false;
596990
- writeFileSync53(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
597328
+ writeFileSync54(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
596991
597329
  }
596992
597330
  }
596993
597331
  function deleteProfile(name10, scope = "global", projectDir2) {
596994
597332
  const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
596995
597333
  const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
596996
- const filePath = join120(dir, `${sanitized}.json`);
596997
- if (existsSync104(filePath)) {
597334
+ const filePath = join121(dir, `${sanitized}.json`);
597335
+ if (existsSync105(filePath)) {
596998
597336
  unlinkSync23(filePath);
596999
597337
  return true;
597000
597338
  }
@@ -597108,24 +597446,24 @@ var init_profiles = __esm({
597108
597446
  });
597109
597447
 
597110
597448
  // packages/cli/src/docker.ts
597111
- import { execSync as execSync56, spawn as spawn24 } from "node:child_process";
597112
- import { existsSync as existsSync105, mkdirSync as mkdirSync62, writeFileSync as writeFileSync54 } from "node:fs";
597113
- import { join as join121, resolve as resolve37, dirname as dirname35 } from "node:path";
597449
+ import { execSync as execSync56, spawn as spawn25 } from "node:child_process";
597450
+ import { existsSync as existsSync106, mkdirSync as mkdirSync63, writeFileSync as writeFileSync55 } from "node:fs";
597451
+ import { join as join122, resolve as resolve37, dirname as dirname35 } from "node:path";
597114
597452
  import { homedir as homedir42 } from "node:os";
597115
597453
  import { fileURLToPath as fileURLToPath16 } from "node:url";
597116
597454
  function getDockerDir() {
597117
597455
  try {
597118
597456
  if (typeof __dirname !== "undefined") {
597119
- return join121(__dirname, "..", "..", "..", "docker");
597457
+ return join122(__dirname, "..", "..", "..", "docker");
597120
597458
  }
597121
597459
  } catch {
597122
597460
  }
597123
597461
  try {
597124
597462
  const thisDir = dirname35(fileURLToPath16(import.meta.url));
597125
- return join121(thisDir, "..", "..", "..", "docker");
597463
+ return join122(thisDir, "..", "..", "..", "docker");
597126
597464
  } catch {
597127
597465
  }
597128
- return join121(process.cwd(), "docker");
597466
+ return join122(process.cwd(), "docker");
597129
597467
  }
597130
597468
  function isDockerAvailable() {
597131
597469
  try {
@@ -597256,11 +597594,11 @@ async function ensureOaImage(force = false) {
597256
597594
  }
597257
597595
  let buildContext;
597258
597596
  const dockerDir = getDockerDir();
597259
- if (existsSync105(join121(dockerDir, "Dockerfile"))) {
597597
+ if (existsSync106(join122(dockerDir, "Dockerfile"))) {
597260
597598
  buildContext = dockerDir;
597261
597599
  } else {
597262
- buildContext = join121(homedir42(), ".oa", "docker-build");
597263
- mkdirSync62(buildContext, { recursive: true });
597600
+ buildContext = join122(homedir42(), ".oa", "docker-build");
597601
+ mkdirSync63(buildContext, { recursive: true });
597264
597602
  writeDockerfiles(buildContext);
597265
597603
  }
597266
597604
  try {
@@ -597334,8 +597672,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
597334
597672
  if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
597335
597673
  exec "$@"
597336
597674
  `;
597337
- writeFileSync54(join121(dir, "Dockerfile"), dockerfile);
597338
- writeFileSync54(join121(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
597675
+ writeFileSync55(join122(dir, "Dockerfile"), dockerfile);
597676
+ writeFileSync55(join122(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
597339
597677
  }
597340
597678
  function hasNvidiaGpu() {
597341
597679
  try {
@@ -597389,7 +597727,7 @@ function runInContainer(opts) {
597389
597727
  if (opts.maxTurns) oaArgs.push("--max-turns", String(opts.maxTurns));
597390
597728
  if (opts.timeoutS) oaArgs.push("--timeout", String(opts.timeoutS));
597391
597729
  args.push(...oaArgs);
597392
- return spawn24("docker", args, {
597730
+ return spawn25("docker", args, {
597393
597731
  stdio: ["ignore", "pipe", "pipe"]
597394
597732
  });
597395
597733
  }
@@ -597588,23 +597926,23 @@ import * as http5 from "node:http";
597588
597926
  import * as https3 from "node:https";
597589
597927
  import { createRequire as createRequire5 } from "node:module";
597590
597928
  import { fileURLToPath as fileURLToPath17 } from "node:url";
597591
- import { dirname as dirname36, join as join122, resolve as resolve38 } from "node:path";
597929
+ import { dirname as dirname36, join as join123, resolve as resolve38 } from "node:path";
597592
597930
  import { homedir as homedir43 } from "node:os";
597593
- import { spawn as spawn25, execSync as execSync57 } from "node:child_process";
597594
- import { mkdirSync as mkdirSync63, writeFileSync as writeFileSync55, readFileSync as readFileSync86, readdirSync as readdirSync36, existsSync as existsSync106, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
597931
+ import { spawn as spawn26, execSync as execSync57 } from "node:child_process";
597932
+ import { mkdirSync as mkdirSync64, writeFileSync as writeFileSync56, readFileSync as readFileSync86, readdirSync as readdirSync36, existsSync as existsSync107, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
597595
597933
  import { randomBytes as randomBytes23, randomUUID as randomUUID16 } from "node:crypto";
597596
597934
  import { createHash as createHash19 } from "node:crypto";
597597
597935
  function getVersion3() {
597598
597936
  try {
597599
597937
  const thisDir = dirname36(fileURLToPath17(import.meta.url));
597600
597938
  const candidates = [
597601
- join122(thisDir, "..", "package.json"),
597602
- join122(thisDir, "..", "..", "package.json"),
597603
- join122(thisDir, "..", "..", "..", "package.json")
597939
+ join123(thisDir, "..", "package.json"),
597940
+ join123(thisDir, "..", "..", "package.json"),
597941
+ join123(thisDir, "..", "..", "..", "package.json")
597604
597942
  ];
597605
597943
  for (const pkgPath of candidates) {
597606
597944
  try {
597607
- if (!existsSync106(pkgPath)) continue;
597945
+ if (!existsSync107(pkgPath)) continue;
597608
597946
  const pkg = require3(pkgPath);
597609
597947
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
597610
597948
  return pkg.version ?? "0.0.0";
@@ -597806,8 +598144,8 @@ function isOriginAllowed(origin) {
597806
598144
  if (!origin) return true;
597807
598145
  let accessMode = (process.env["OA_ACCESS"] || "").toLowerCase().trim();
597808
598146
  try {
597809
- const accessFile = join122(homedir43(), ".open-agents", "access");
597810
- if (existsSync106(accessFile)) {
598147
+ const accessFile = join123(homedir43(), ".open-agents", "access");
598148
+ if (existsSync107(accessFile)) {
597811
598149
  const persisted = readFileSync86(accessFile, "utf8").trim().toLowerCase();
597812
598150
  if (persisted === "any" || persisted === "lan" || persisted === "loopback") {
597813
598151
  accessMode = persisted;
@@ -597868,7 +598206,7 @@ async function retrieveMemoryContext(userMessage, sessionId, maxEpisodes = 5) {
597868
598206
  if (!memMod || !memMod.EpisodeStore) {
597869
598207
  return { contextBlock: "", retrieved: [] };
597870
598208
  }
597871
- const dbPath = join122(homedir43(), ".open-agents", "memory.db");
598209
+ const dbPath = join123(homedir43(), ".open-agents", "memory.db");
597872
598210
  const store2 = new memMod.EpisodeStore(dbPath);
597873
598211
  const recent = store2.search({ limit: 30, sessionId: void 0 }) ?? [];
597874
598212
  const qLower = userMessage.toLowerCase();
@@ -597911,7 +598249,7 @@ async function writeMemoryEpisodes(sessionId, userMessage, assistantContent, too
597911
598249
  try {
597912
598250
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2)).catch(() => null);
597913
598251
  if (!memMod || !memMod.EpisodeStore) return 0;
597914
- const dbPath = join122(homedir43(), ".open-agents", "memory.db");
598252
+ const dbPath = join123(homedir43(), ".open-agents", "memory.db");
597915
598253
  const store2 = new memMod.EpisodeStore(dbPath);
597916
598254
  let written = 0;
597917
598255
  try {
@@ -598233,13 +598571,13 @@ function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError, ti
598233
598571
  }
598234
598572
  function jobsDir() {
598235
598573
  const root = resolve38(process.cwd());
598236
- const dir = join122(root, ".oa", "jobs");
598237
- mkdirSync63(dir, { recursive: true });
598574
+ const dir = join123(root, ".oa", "jobs");
598575
+ mkdirSync64(dir, { recursive: true });
598238
598576
  return dir;
598239
598577
  }
598240
598578
  function loadJob(id) {
598241
- const file = join122(jobsDir(), `${id}.json`);
598242
- if (!existsSync106(file)) return null;
598579
+ const file = join123(jobsDir(), `${id}.json`);
598580
+ if (!existsSync107(file)) return null;
598243
598581
  try {
598244
598582
  return JSON.parse(readFileSync86(file, "utf-8"));
598245
598583
  } catch {
@@ -598248,12 +598586,12 @@ function loadJob(id) {
598248
598586
  }
598249
598587
  function listJobs() {
598250
598588
  const dir = jobsDir();
598251
- if (!existsSync106(dir)) return [];
598589
+ if (!existsSync107(dir)) return [];
598252
598590
  const files = readdirSync36(dir).filter((f2) => f2.endsWith(".json")).sort();
598253
598591
  const jobs = [];
598254
598592
  for (const file of files) {
598255
598593
  try {
598256
- jobs.push(JSON.parse(readFileSync86(join122(dir, file), "utf-8")));
598594
+ jobs.push(JSON.parse(readFileSync86(join123(dir, file), "utf-8")));
598257
598595
  } catch {
598258
598596
  }
598259
598597
  }
@@ -598263,12 +598601,12 @@ function pruneOldJobs() {
598263
598601
  const retentionH = parseFloat(process.env["OA_RUN_RETENTION_H"] || "24");
598264
598602
  const cutoffMs = Date.now() - (Number.isFinite(retentionH) && retentionH > 0 ? retentionH : 24) * 36e5;
598265
598603
  const dir = jobsDir();
598266
- if (!existsSync106(dir)) return { pruned: 0, kept: 0 };
598604
+ if (!existsSync107(dir)) return { pruned: 0, kept: 0 };
598267
598605
  let pruned = 0;
598268
598606
  let kept = 0;
598269
598607
  for (const file of readdirSync36(dir)) {
598270
598608
  if (!file.endsWith(".json")) continue;
598271
- const path8 = join122(dir, file);
598609
+ const path8 = join123(dir, file);
598272
598610
  try {
598273
598611
  const job = JSON.parse(readFileSync86(path8, "utf-8"));
598274
598612
  if (job.status === "running") {
@@ -598283,7 +598621,7 @@ function pruneOldJobs() {
598283
598621
  } catch {
598284
598622
  }
598285
598623
  const outFile = path8.replace(/\.json$/, ".output");
598286
- if (existsSync106(outFile)) {
598624
+ if (existsSync107(outFile)) {
598287
598625
  try {
598288
598626
  unlinkSync24(outFile);
598289
598627
  } catch {
@@ -598576,14 +598914,14 @@ function autoSeedTodosFromPrompt(prompt) {
598576
598914
  return [];
598577
598915
  }
598578
598916
  function atomicJobWrite(dir, id, job) {
598579
- const finalPath = join122(dir, `${id}.json`);
598917
+ const finalPath = join123(dir, `${id}.json`);
598580
598918
  const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
598581
598919
  try {
598582
- writeFileSync55(tmpPath, JSON.stringify(job, null, 2), "utf-8");
598920
+ writeFileSync56(tmpPath, JSON.stringify(job, null, 2), "utf-8");
598583
598921
  renameSync8(tmpPath, finalPath);
598584
598922
  } catch {
598585
598923
  try {
598586
- writeFileSync55(finalPath, JSON.stringify(job, null, 2), "utf-8");
598924
+ writeFileSync56(finalPath, JSON.stringify(job, null, 2), "utf-8");
598587
598925
  } catch {
598588
598926
  }
598589
598927
  try {
@@ -599785,7 +600123,7 @@ ${task}` : task;
599785
600123
  runEnv["OA_RUN_SCOPE"] = req2._authScope || "admin";
599786
600124
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
599787
600125
  if (currentCfg.apiKey) runEnv["OA_API_KEY_INHERIT"] = currentCfg.apiKey;
599788
- const child = spawn25(process.execPath, [oaBin, ...args], {
600126
+ const child = spawn26(process.execPath, [oaBin, ...args], {
599789
600127
  cwd: resolve38(process.cwd()),
599790
600128
  env: runEnv,
599791
600129
  stdio: ["ignore", "pipe", "pipe"]
@@ -600002,15 +600340,15 @@ ${task}` : task;
600002
600340
  });
600003
600341
  }
600004
600342
  function updateStateFile() {
600005
- return join122(homedir43(), ".open-agents", "update-state.json");
600343
+ return join123(homedir43(), ".open-agents", "update-state.json");
600006
600344
  }
600007
600345
  function updateLogPath() {
600008
- return join122(homedir43(), ".open-agents", "update.log");
600346
+ return join123(homedir43(), ".open-agents", "update.log");
600009
600347
  }
600010
600348
  function readUpdateState() {
600011
600349
  try {
600012
600350
  const p2 = updateStateFile();
600013
- if (!existsSync106(p2)) return null;
600351
+ if (!existsSync107(p2)) return null;
600014
600352
  return JSON.parse(readFileSync86(p2, "utf-8"));
600015
600353
  } catch {
600016
600354
  return null;
@@ -600018,11 +600356,11 @@ function readUpdateState() {
600018
600356
  }
600019
600357
  function writeUpdateState(state) {
600020
600358
  try {
600021
- const dir = join122(homedir43(), ".open-agents");
600022
- mkdirSync63(dir, { recursive: true });
600359
+ const dir = join123(homedir43(), ".open-agents");
600360
+ mkdirSync64(dir, { recursive: true });
600023
600361
  const finalPath = updateStateFile();
600024
600362
  const tmpPath = `${finalPath}.tmp.${process.pid}`;
600025
- writeFileSync55(tmpPath, JSON.stringify(state, null, 2), "utf-8");
600363
+ writeFileSync56(tmpPath, JSON.stringify(state, null, 2), "utf-8");
600026
600364
  renameSync8(tmpPath, finalPath);
600027
600365
  } catch {
600028
600366
  }
@@ -600066,15 +600404,15 @@ async function handleV1Update(req2, res, requestId) {
600066
600404
  const { execSync: es } = require3("node:child_process");
600067
600405
  const isWin2 = process.platform === "win32";
600068
600406
  let npmBin = "";
600069
- for (const candidate of isWin2 ? [join122(nodeDir, "npm.cmd"), join122(nodeDir, "npm")] : [join122(nodeDir, "npm"), "/usr/local/bin/npm", "/usr/bin/npm"]) {
600070
- if (existsSync106(candidate)) {
600407
+ for (const candidate of isWin2 ? [join123(nodeDir, "npm.cmd"), join123(nodeDir, "npm")] : [join123(nodeDir, "npm"), "/usr/local/bin/npm", "/usr/bin/npm"]) {
600408
+ if (existsSync107(candidate)) {
600071
600409
  npmBin = candidate;
600072
600410
  break;
600073
600411
  }
600074
600412
  }
600075
600413
  if (!npmBin) npmBin = isWin2 ? "npm.cmd" : "npm";
600076
600414
  const pkgSpec = `open-agents-ai@${targetVersion}`;
600077
- const dir = join122(homedir43(), ".open-agents");
600415
+ const dir = join123(homedir43(), ".open-agents");
600078
600416
  fs7.mkdirSync(dir, { recursive: true });
600079
600417
  const logFd = fs7.openSync(logPath3, "w");
600080
600418
  const npmPrefix = dirname36(nodeDir);
@@ -600084,13 +600422,13 @@ async function handleV1Update(req2, res, requestId) {
600084
600422
  globalBinDir = es(`${npmBin} bin -g`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
600085
600423
  } else {
600086
600424
  const npmCliCandidates = [
600087
- join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600088
- join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600425
+ join123(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600426
+ join123(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600089
600427
  ];
600090
600428
  let npmCli = "";
600091
600429
  for (const c9 of npmCliCandidates) {
600092
600430
  try {
600093
- if (existsSync106(c9)) {
600431
+ if (existsSync107(c9)) {
600094
600432
  npmCli = c9;
600095
600433
  break;
600096
600434
  }
@@ -600114,7 +600452,7 @@ async function handleV1Update(req2, res, requestId) {
600114
600452
  cleanEnv.PATH = pathParts.join(":");
600115
600453
  let child;
600116
600454
  if (isWin2) {
600117
- child = spawn25(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600455
+ child = spawn26(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600118
600456
  detached: true,
600119
600457
  stdio: ["ignore", logFd, logFd],
600120
600458
  windowsHide: true,
@@ -600122,13 +600460,13 @@ async function handleV1Update(req2, res, requestId) {
600122
600460
  });
600123
600461
  } else {
600124
600462
  const npmCliCandidates = [
600125
- join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600126
- join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600463
+ join123(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600464
+ join123(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600127
600465
  ];
600128
600466
  let npmCli = "";
600129
600467
  for (const c9 of npmCliCandidates) {
600130
600468
  try {
600131
- if (existsSync106(c9)) {
600469
+ if (existsSync107(c9)) {
600132
600470
  npmCli = c9;
600133
600471
  break;
600134
600472
  }
@@ -600136,13 +600474,13 @@ async function handleV1Update(req2, res, requestId) {
600136
600474
  }
600137
600475
  }
600138
600476
  if (npmCli) {
600139
- child = spawn25(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600477
+ child = spawn26(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600140
600478
  detached: true,
600141
600479
  stdio: ["ignore", logFd, logFd],
600142
600480
  env: cleanEnv
600143
600481
  });
600144
600482
  } else {
600145
- child = spawn25(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600483
+ child = spawn26(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600146
600484
  detached: true,
600147
600485
  stdio: ["ignore", logFd, logFd],
600148
600486
  env: cleanEnv
@@ -600153,7 +600491,7 @@ async function handleV1Update(req2, res, requestId) {
600153
600491
  const installPid = child.pid ?? 0;
600154
600492
  if (installPid > 0 && !isWin2) {
600155
600493
  try {
600156
- const follower = spawn25("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
600494
+ const follower = spawn26("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
600157
600495
  detached: true,
600158
600496
  stdio: "ignore"
600159
600497
  });
@@ -600166,8 +600504,8 @@ async function handleV1Update(req2, res, requestId) {
600166
600504
  }
600167
600505
  let oaAbs = "oa";
600168
600506
  try {
600169
- const which = es("command -v oa 2>/dev/null || which oa 2>/dev/null", { encoding: "utf8", timeout: 2e3, stdio: "pipe", env: cleanEnv }).trim();
600170
- if (which) oaAbs = which;
600507
+ const which2 = es("command -v oa 2>/dev/null || which oa 2>/dev/null", { encoding: "utf8", timeout: 2e3, stdio: "pipe", env: cleanEnv }).trim();
600508
+ if (which2) oaAbs = which2;
600171
600509
  } catch {
600172
600510
  }
600173
600511
  const relaunchScript = [
@@ -600176,7 +600514,7 @@ async function handleV1Update(req2, res, requestId) {
600176
600514
  hasSystemdUnit ? `systemctl --user restart open-agents-daemon.service >/dev/null 2>&1 || true` : `${JSON.stringify(oaAbs)} serve --quiet --daemon >/dev/null 2>&1 & disown`,
600177
600515
  `kill -TERM ${process.pid} >/dev/null 2>&1 || true`
600178
600516
  ].join("; ");
600179
- const relauncher = spawn25("bash", ["-c", relaunchScript], {
600517
+ const relauncher = spawn26("bash", ["-c", relaunchScript], {
600180
600518
  detached: true,
600181
600519
  stdio: "ignore",
600182
600520
  env: cleanEnv
@@ -600225,7 +600563,7 @@ function handleV1UpdateStatus(res) {
600225
600563
  let logTail = "";
600226
600564
  let exitCode = null;
600227
600565
  try {
600228
- if (existsSync106(logPath3)) {
600566
+ if (existsSync107(logPath3)) {
600229
600567
  const raw = readFileSync86(logPath3, "utf-8");
600230
600568
  const m2 = raw.match(/__EXIT_CODE=(\d+)/);
600231
600569
  if (m2) exitCode = parseInt(m2[1], 10);
@@ -600322,8 +600660,8 @@ async function handleV1Run(req2, res) {
600322
600660
  if (workingDir) {
600323
600661
  cwd4 = resolve38(workingDir);
600324
600662
  } else if (isolate) {
600325
- const wsDir = join122(dir, "..", "workspaces", id);
600326
- mkdirSync63(wsDir, { recursive: true });
600663
+ const wsDir = join123(dir, "..", "workspaces", id);
600664
+ mkdirSync64(wsDir, { recursive: true });
600327
600665
  cwd4 = wsDir;
600328
600666
  } else {
600329
600667
  cwd4 = resolve38(process.cwd());
@@ -600398,7 +600736,7 @@ async function handleV1Run(req2, res) {
600398
600736
  });
600399
600737
  job.sandbox = "container";
600400
600738
  } else {
600401
- child = spawn25(process.execPath, [oaBin, ...args], {
600739
+ child = spawn26(process.execPath, [oaBin, ...args], {
600402
600740
  cwd: cwd4,
600403
600741
  env: runEnv,
600404
600742
  stdio: ["ignore", "pipe", "pipe"],
@@ -600509,7 +600847,7 @@ async function handleV1Run(req2, res) {
600509
600847
  let output = "";
600510
600848
  let tailBytes = 0;
600511
600849
  const TAIL_BUDGET = 1048576;
600512
- const outputWriter = new DiskTaskOutput(join122(dir, `${id}.output`));
600850
+ const outputWriter = new DiskTaskOutput(join123(dir, `${id}.output`));
600513
600851
  job.outputFile = outputWriter.path;
600514
600852
  atomicJobWrite(dir, id, job);
600515
600853
  child.stdout?.on("data", (chunk) => {
@@ -600908,7 +601246,7 @@ async function handlePostCommand(res, cmd) {
600908
601246
  return;
600909
601247
  }
600910
601248
  try {
600911
- const child = spawn25("node", [oaBin, "run", `/${cmd}`, "--json"], {
601249
+ const child = spawn26("node", [oaBin, "run", `/${cmd}`, "--json"], {
600912
601250
  env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
600913
601251
  stdio: ["ignore", "pipe", "pipe"],
600914
601252
  timeout: 3e4
@@ -601425,11 +601763,11 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
601425
601763
  jsonResponse(res, 400, { error: "audio_too_small", message: "Reference audio must be at least ~4 KB" });
601426
601764
  return;
601427
601765
  }
601428
- const { tmpdir: tmpdir22 } = await import("node:os");
601429
- const { writeFileSync: writeFileSync59, unlinkSync: unlinkSync25 } = await import("node:fs");
601766
+ const { tmpdir: tmpdir23 } = await import("node:os");
601767
+ const { writeFileSync: writeFileSync60, unlinkSync: unlinkSync25 } = await import("node:fs");
601430
601768
  const { join: pjoin } = await import("node:path");
601431
- const tmpPath = pjoin(tmpdir22(), `oa-clone-upload-${Date.now()}-${safeName}`);
601432
- writeFileSync59(tmpPath, buf);
601769
+ const tmpPath = pjoin(tmpdir23(), `oa-clone-upload-${Date.now()}-${safeName}`);
601770
+ writeFileSync60(tmpPath, buf);
601433
601771
  try {
601434
601772
  const ve = getVoiceEngine();
601435
601773
  const msg = await ve.setCloneVoice(tmpPath);
@@ -601979,7 +602317,7 @@ data: ${JSON.stringify(data)}
601979
602317
  }
601980
602318
  for (const f2 of seenFiles) {
601981
602319
  try {
601982
- writeFileSync55(f2, JSON.stringify({ tasks: [] }, null, 2));
602320
+ writeFileSync56(f2, JSON.stringify({ tasks: [] }, null, 2));
601983
602321
  deleted++;
601984
602322
  } catch {
601985
602323
  }
@@ -602280,7 +602618,7 @@ ${historyLines}
602280
602618
  }
602281
602619
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
602282
602620
  if (currentCfg.apiKey) runEnv["OA_API_KEY_INHERIT"] = currentCfg.apiKey;
602283
- const child = spawn25(process.execPath, [oaBin, ...args], {
602621
+ const child = spawn26(process.execPath, [oaBin, ...args], {
602284
602622
  cwd: cwdPath,
602285
602623
  env: runEnv,
602286
602624
  stdio: ["ignore", "pipe", "pipe"],
@@ -603083,7 +603421,7 @@ ${steering}`;
603083
603421
  function getScheduleRoots() {
603084
603422
  const rootsEnv = process.env["OA_SCHEDULE_ROOTS"] || "";
603085
603423
  const roots = rootsEnv.split(rootsEnv.includes(";") ? ";" : ":").filter(Boolean);
603086
- const defaults3 = [process.cwd(), join122(homedir43(), "Documents")];
603424
+ const defaults3 = [process.cwd(), join123(homedir43(), "Documents")];
603087
603425
  const set = /* @__PURE__ */ new Set([...defaults3, ...roots]);
603088
603426
  return [...set];
603089
603427
  }
@@ -603095,8 +603433,8 @@ function listScheduledTasks() {
603095
603433
  for (const root of roots) {
603096
603434
  try {
603097
603435
  walk(root, 0, (dir) => {
603098
- if (dir.endsWith(`${join122(".oa", "scheduled")}`) || dir.includes(`${join122(".oa", "scheduled")}`)) {
603099
- const file = join122(dir, "tasks.json");
603436
+ if (dir.endsWith(`${join123(".oa", "scheduled")}`) || dir.includes(`${join123(".oa", "scheduled")}`)) {
603437
+ const file = join123(dir, "tasks.json");
603100
603438
  try {
603101
603439
  const raw = readFileSync86(file, "utf-8");
603102
603440
  const json = JSON.parse(raw);
@@ -603163,7 +603501,7 @@ function walk(dir, depth, onDir, maxDepth) {
603163
603501
  if (e2.name === "node_modules" || e2.name.startsWith(".")) {
603164
603502
  if (e2.name !== ".oa") continue;
603165
603503
  }
603166
- const child = join122(dir, e2.name);
603504
+ const child = join123(dir, e2.name);
603167
603505
  walk(child, depth + 1, onDir, maxDepth);
603168
603506
  }
603169
603507
  }
@@ -603179,11 +603517,11 @@ function setScheduledEnabled(id, enabled2) {
603179
603517
  arr[target.index].enabled = enabled2;
603180
603518
  if (Array.isArray(json?.tasks)) {
603181
603519
  json.tasks = arr;
603182
- writeFileSync55(target.file, JSON.stringify(json, null, 2));
603520
+ writeFileSync56(target.file, JSON.stringify(json, null, 2));
603183
603521
  } else if (Array.isArray(json)) {
603184
- writeFileSync55(target.file, JSON.stringify(arr, null, 2));
603522
+ writeFileSync56(target.file, JSON.stringify(arr, null, 2));
603185
603523
  } else {
603186
- writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
603524
+ writeFileSync56(target.file, JSON.stringify({ tasks: arr }, null, 2));
603187
603525
  }
603188
603526
  if (!enabled2) {
603189
603527
  try {
@@ -603213,11 +603551,11 @@ function deleteScheduledById(id) {
603213
603551
  arr.splice(target.index, 1);
603214
603552
  if (Array.isArray(json?.tasks)) {
603215
603553
  json.tasks = arr;
603216
- writeFileSync55(target.file, JSON.stringify(json, null, 2));
603554
+ writeFileSync56(target.file, JSON.stringify(json, null, 2));
603217
603555
  } else if (Array.isArray(json)) {
603218
- writeFileSync55(target.file, JSON.stringify(arr, null, 2));
603556
+ writeFileSync56(target.file, JSON.stringify(arr, null, 2));
603219
603557
  } else {
603220
- writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
603558
+ writeFileSync56(target.file, JSON.stringify({ tasks: arr }, null, 2));
603221
603559
  }
603222
603560
  const candidates = [];
603223
603561
  if (id) candidates.push(id);
@@ -603470,7 +603808,7 @@ function reconcileScheduledTasks(apply) {
603470
603808
  const errors = [];
603471
603809
  for (const f2 of found) {
603472
603810
  const wdir = f2.workingDir || process.cwd();
603473
- const file = join122(wdir, ".oa", "scheduled", "tasks.json");
603811
+ const file = join123(wdir, ".oa", "scheduled", "tasks.json");
603474
603812
  try {
603475
603813
  let json = { tasks: [] };
603476
603814
  try {
@@ -603485,9 +603823,9 @@ function reconcileScheduledTasks(apply) {
603485
603823
  const entry = { task: f2.task || `legacy ${f2.id}`, schedule: f2.cron, enabled: true };
603486
603824
  arr.push(entry);
603487
603825
  const toWrite = Array.isArray(json?.tasks) ? { ...json, tasks: arr } : Array.isArray(json) ? arr : { tasks: arr };
603488
- mkdirSync63(join122(wdir, ".oa", "scheduled"), { recursive: true });
603489
- mkdirSync63(join122(wdir, ".oa", "scheduled", "logs"), { recursive: true });
603490
- writeFileSync55(file, JSON.stringify(toWrite, null, 2));
603826
+ mkdirSync64(join123(wdir, ".oa", "scheduled"), { recursive: true });
603827
+ mkdirSync64(join123(wdir, ".oa", "scheduled", "logs"), { recursive: true });
603828
+ writeFileSync56(file, JSON.stringify(toWrite, null, 2));
603491
603829
  adopted.push({ file, index: arr.length - 1 });
603492
603830
  }
603493
603831
  } else {
@@ -603531,32 +603869,32 @@ function writeCrontabLines(lines) {
603531
603869
  }
603532
603870
  function canonicalCronLine(rec) {
603533
603871
  const oaBin = findOaBinary4();
603534
- const logDir = join122(rec.workingDir, ".oa", "scheduled", "logs");
603535
- const logFile = join122(logDir, `${rec.id}.log`);
603536
- const storeFile = join122(rec.workingDir, ".oa", "scheduled", "tasks.json");
603872
+ const logDir = join123(rec.workingDir, ".oa", "scheduled", "logs");
603873
+ const logFile = join123(logDir, `${rec.id}.log`);
603874
+ const storeFile = join123(rec.workingDir, ".oa", "scheduled", "tasks.json");
603537
603875
  const taskEsc = rec.task.replace(/'/g, "'\\''");
603538
- const lockDir = join122(rec.workingDir, ".oa", "run");
603539
- const lockPath = join122(lockDir, `${rec.id}.lock`);
603876
+ const lockDir = join123(rec.workingDir, ".oa", "run");
603877
+ const lockPath = join123(lockDir, `${rec.id}.lock`);
603540
603878
  const wrapper = [
603541
603879
  `cd ${JSON.stringify(rec.workingDir)}`,
603542
603880
  `mkdir -p ${JSON.stringify(logDir)}`,
603543
603881
  `mkdir -p ${JSON.stringify(lockDir)}`,
603544
603882
  `if mkdir ${JSON.stringify(lockPath)} 2>/dev/null; then`,
603545
- ` echo $$ > ${JSON.stringify(join122(lockPath, "pid"))}`,
603883
+ ` echo $$ > ${JSON.stringify(join123(lockPath, "pid"))}`,
603546
603884
  ` trap 'rm -rf ${lockPath}' EXIT`,
603547
603885
  `else`,
603548
- ` if [ -f ${JSON.stringify(join122(lockPath, "pid"))} ]; then`,
603549
- ` oldpid=$(cat ${JSON.stringify(join122(lockPath, "pid"))} 2>/dev/null || echo)`,
603886
+ ` if [ -f ${JSON.stringify(join123(lockPath, "pid"))} ]; then`,
603887
+ ` oldpid=$(cat ${JSON.stringify(join123(lockPath, "pid"))} 2>/dev/null || echo)`,
603550
603888
  ` if [ -n "$oldpid" ] && kill -0 "$oldpid" 2>/dev/null; then`,
603551
603889
  ` echo "[oa-scheduler] ${rec.id} already running as PID $oldpid; skipping" >> ${JSON.stringify(logFile)}`,
603552
603890
  ` exit 0`,
603553
603891
  ` else`,
603554
603892
  ` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
603555
- ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join122(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603893
+ ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join123(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603556
603894
  ` fi`,
603557
603895
  ` else`,
603558
603896
  ` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
603559
- ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join122(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603897
+ ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join123(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603560
603898
  ` fi`,
603561
603899
  `fi`,
603562
603900
  `${oaBin} '${taskEsc}' >> ${JSON.stringify(logFile)} 2>&1; _oa_exit=$?`,
@@ -603588,9 +603926,9 @@ function fixupOrMigrateScheduled(mode, dryRun) {
603588
603926
  try {
603589
603927
  if (!f2.workingDir || !f2.task) continue;
603590
603928
  const unitBase = `oa-${f2.id}`;
603591
- const unitDir = join122(homedir43(), ".config", "systemd", "user");
603592
- const svc = join122(unitDir, `${unitBase}.service`);
603593
- const tim = join122(unitDir, `${unitBase}.timer`);
603929
+ const unitDir = join123(homedir43(), ".config", "systemd", "user");
603930
+ const svc = join123(unitDir, `${unitBase}.service`);
603931
+ const tim = join123(unitDir, `${unitBase}.timer`);
603594
603932
  const oaBin = findOaBinary4();
603595
603933
  const rec = { id: f2.id, cron: f2.cron, workingDir: f2.workingDir, task: f2.task };
603596
603934
  const cmd = canonicalCronLine(rec).split(" ").slice(5).join(" ");
@@ -603620,9 +603958,9 @@ Persistent=true
603620
603958
  WantedBy=timers.target
603621
603959
  `;
603622
603960
  if (!dryRun) {
603623
- mkdirSync63(unitDir, { recursive: true });
603624
- writeFileSync55(svc, svcText);
603625
- writeFileSync55(tim, timText);
603961
+ mkdirSync64(unitDir, { recursive: true });
603962
+ writeFileSync56(svc, svcText);
603963
+ writeFileSync56(tim, timText);
603626
603964
  try {
603627
603965
  const { execSync: es } = require3("node:child_process");
603628
603966
  es("systemctl --user daemon-reload", { stdio: "pipe" });
@@ -603716,8 +604054,8 @@ function startApiServer(options2 = {}) {
603716
604054
  const config = loadConfig();
603717
604055
  const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
603718
604056
  const cwd4 = process.cwd();
603719
- initAuditLog(join122(cwd4, ".oa"));
603720
- initUsageTracker(join122(cwd4, ".oa"));
604057
+ initAuditLog(join123(cwd4, ".oa"));
604058
+ initUsageTracker(join123(cwd4, ".oa"));
603721
604059
  try {
603722
604060
  const taskMgr = getSharedTaskManager();
603723
604061
  taskMgr.setEventPublisher((type, data, opts) => {
@@ -603759,7 +604097,7 @@ function startApiServer(options2 = {}) {
603759
604097
  try {
603760
604098
  const dir = todoDir();
603761
604099
  try {
603762
- mkdirSync63(dir, { recursive: true });
604100
+ mkdirSync64(dir, { recursive: true });
603763
604101
  } catch {
603764
604102
  }
603765
604103
  const cache8 = /* @__PURE__ */ new Map();
@@ -603768,7 +604106,7 @@ function startApiServer(options2 = {}) {
603768
604106
  if (!f2.endsWith(".json") || f2.includes(".tmp.")) continue;
603769
604107
  const sid = f2.replace(/\.json$/, "");
603770
604108
  try {
603771
- const items = JSON.parse(readFileSync86(join122(dir, f2), "utf-8"));
604109
+ const items = JSON.parse(readFileSync86(join123(dir, f2), "utf-8"));
603772
604110
  if (Array.isArray(items)) {
603773
604111
  cache8.set(sid, new Map(items.map((t2) => [t2.id, t2])));
603774
604112
  }
@@ -603780,10 +604118,10 @@ function startApiServer(options2 = {}) {
603780
604118
  const watcher = fsWatch3(dir, (_evt, fname) => {
603781
604119
  if (!fname || !fname.endsWith(".json") || fname.includes(".tmp.")) return;
603782
604120
  const sid = fname.replace(/\.json$/, "");
603783
- const fp = join122(dir, fname);
604121
+ const fp = join123(dir, fname);
603784
604122
  let next = [];
603785
604123
  try {
603786
- if (!existsSync106(fp)) {
604124
+ if (!existsSync107(fp)) {
603787
604125
  const old = cache8.get(sid);
603788
604126
  if (old) {
603789
604127
  for (const t2 of old.values()) {
@@ -603835,13 +604173,13 @@ function startApiServer(options2 = {}) {
603835
604173
  const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
603836
604174
  if (retentionDays > 0) {
603837
604175
  try {
603838
- const jobsDir3 = join122(cwd4, ".oa", "jobs");
603839
- if (existsSync106(jobsDir3)) {
604176
+ const jobsDir3 = join123(cwd4, ".oa", "jobs");
604177
+ if (existsSync107(jobsDir3)) {
603840
604178
  const cutoff = Date.now() - retentionDays * 864e5;
603841
604179
  for (const f2 of readdirSync36(jobsDir3)) {
603842
604180
  if (!f2.endsWith(".json")) continue;
603843
604181
  try {
603844
- const jobPath = join122(jobsDir3, f2);
604182
+ const jobPath = join123(jobsDir3, f2);
603845
604183
  const job = JSON.parse(readFileSync86(jobPath, "utf-8"));
603846
604184
  const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
603847
604185
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
@@ -603874,8 +604212,8 @@ function startApiServer(options2 = {}) {
603874
604212
  }
603875
604213
  let runtimeAccessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
603876
604214
  try {
603877
- const accessFile = join122(homedir43(), ".open-agents", "access");
603878
- if (existsSync106(accessFile)) {
604215
+ const accessFile = join123(homedir43(), ".open-agents", "access");
604216
+ if (existsSync107(accessFile)) {
603879
604217
  const persisted = readFileSync86(accessFile, "utf8").trim();
603880
604218
  const resolved = resolveAccessMode(persisted, host);
603881
604219
  if (resolved) runtimeAccessMode = resolved;
@@ -603929,9 +604267,9 @@ function startApiServer(options2 = {}) {
603929
604267
  const previous = runtimeAccessMode;
603930
604268
  runtimeAccessMode = requested;
603931
604269
  try {
603932
- const dir = join122(homedir43(), ".open-agents");
603933
- mkdirSync63(dir, { recursive: true });
603934
- writeFileSync55(join122(dir, "access"), `${runtimeAccessMode}
604270
+ const dir = join123(homedir43(), ".open-agents");
604271
+ mkdirSync64(dir, { recursive: true });
604272
+ writeFileSync56(join123(dir, "access"), `${runtimeAccessMode}
603935
604273
  `, "utf8");
603936
604274
  } catch {
603937
604275
  }
@@ -604144,9 +604482,9 @@ function startApiServer(options2 = {}) {
604144
604482
  try {
604145
604483
  const { startEmbeddingWorkers: startEmbeddingWorkers2 } = await Promise.resolve().then(() => (init_embedding_workers(), embedding_workers_exports));
604146
604484
  const { ensureEmbedDeps: ensureEmbedDeps2, runEmbedImage: runEmbedImage2, runEmbedAudio: runEmbedAudio2 } = await Promise.resolve().then(() => (init_py_embed(), py_embed_exports));
604147
- const dbBase = join122(cwd4, ".oa");
604148
- const epStore = new mem.EpisodeStore(join122(dbBase, "memory.db"));
604149
- const kg = new mem.TemporalGraph(join122(dbBase, "kg.db"));
604485
+ const dbBase = join123(cwd4, ".oa");
604486
+ const epStore = new mem.EpisodeStore(join123(dbBase, "memory.db"));
604487
+ const kg = new mem.TemporalGraph(join123(dbBase, "kg.db"));
604150
604488
  try {
604151
604489
  ensureEmbedDeps2();
604152
604490
  } catch {
@@ -604224,7 +604562,7 @@ function startApiServer(options2 = {}) {
604224
604562
  log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
604225
604563
  `);
604226
604564
  try {
604227
- const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: _exists, readFileSync: _rfs } = require3("node:fs");
604565
+ const { writeFileSync: writeFileSync60, mkdirSync: mkdirSync68, existsSync: _exists, readFileSync: _rfs } = require3("node:fs");
604228
604566
  const { join: _join } = require3("node:path");
604229
604567
  const { homedir: _homedir } = require3("node:os");
604230
604568
  const apiHint = JSON.stringify({
@@ -604254,8 +604592,8 @@ function startApiServer(options2 = {}) {
604254
604592
  let written = 0;
604255
604593
  for (const dir of dirSet) {
604256
604594
  try {
604257
- if (!_exists(dir)) mkdirSync67(dir, { recursive: true });
604258
- writeFileSync59(_join(dir, "api-port.json"), apiHint);
604595
+ if (!_exists(dir)) mkdirSync68(dir, { recursive: true });
604596
+ writeFileSync60(_join(dir, "api-port.json"), apiHint);
604259
604597
  written++;
604260
604598
  } catch {
604261
604599
  }
@@ -604266,6 +604604,80 @@ function startApiServer(options2 = {}) {
604266
604604
  log22(` WARN: api-port hint write failed: ${e2.message}
604267
604605
  `);
604268
604606
  }
604607
+ if (process.env["OA_AUTO_NEXUS"] !== "0") {
604608
+ (async () => {
604609
+ try {
604610
+ const { join: _j } = require3("node:path");
604611
+ const { homedir: _hd } = require3("node:os");
604612
+ const { existsSync: _ex, readFileSync: _rf, statSync: _st } = require3("node:fs");
604613
+ const { execSync: _ex2 } = require3("node:child_process");
604614
+ let chosenNexusDir = null;
604615
+ if (process.env["OA_NEXUS_DIR"]) chosenNexusDir = process.env["OA_NEXUS_DIR"];
604616
+ if (!chosenNexusDir) {
604617
+ try {
604618
+ const regPath = _j(_hd(), ".open-agents", "nexus-registry.json");
604619
+ if (_ex(regPath)) {
604620
+ const reg = JSON.parse(_rf(regPath, "utf-8"));
604621
+ for (const e2 of reg?.dirs || []) {
604622
+ const d2 = typeof e2 === "string" ? e2 : e2?.dir;
604623
+ if (typeof d2 === "string" && _ex(d2)) {
604624
+ chosenNexusDir = d2;
604625
+ break;
604626
+ }
604627
+ }
604628
+ }
604629
+ } catch {
604630
+ }
604631
+ }
604632
+ if (!chosenNexusDir) {
604633
+ try {
604634
+ const cmd = `find "${_hd()}" -maxdepth 4 -path '*/.oa/nexus' -type d 2>/dev/null | head -10`;
604635
+ const out = _ex2(cmd, { encoding: "utf-8", timeout: 2e3 }).trim();
604636
+ for (const ln of out.split("\n").filter(Boolean)) {
604637
+ if (_ex(_j(ln, "status.json"))) {
604638
+ chosenNexusDir = ln;
604639
+ break;
604640
+ }
604641
+ }
604642
+ if (!chosenNexusDir && out) chosenNexusDir = out.split("\n")[0]?.trim() || null;
604643
+ } catch {
604644
+ }
604645
+ }
604646
+ const finalNexusDir = chosenNexusDir ?? _j(_hd(), ".oa", "nexus");
604647
+ chosenNexusDir = finalNexusDir;
604648
+ const repoRoot = finalNexusDir.replace(/[\\/]\.oa[\\/]nexus$/, "");
604649
+ log22(` Nexus auto-recover: target ${finalNexusDir}
604650
+ `);
604651
+ const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
604652
+ const tool = new NexusTool2(repoRoot);
604653
+ const result = await tool.execute({ action: "connect" });
604654
+ const status = result?.success ? "ok" : "fail";
604655
+ const detail = result?.output || result?.error || "";
604656
+ log22(` Nexus auto-recover: ${status}${detail ? " — " + String(detail).split("\n")[0].slice(0, 120) : ""}
604657
+ `);
604658
+ if (status === "ok") {
604659
+ try {
604660
+ const { writeFileSync: _wfs2, mkdirSync: _mks, existsSync: _exf } = require3("node:fs");
604661
+ const apiHint2 = JSON.stringify({
604662
+ port,
604663
+ host: host === "0.0.0.0" ? "127.0.0.1" : host,
604664
+ scheme: proto,
604665
+ pid: process.pid,
604666
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
604667
+ version: version4
604668
+ }, null, 2);
604669
+ const dirOut = chosenNexusDir;
604670
+ if (!_exf(dirOut)) _mks(dirOut, { recursive: true });
604671
+ _wfs2(_j(dirOut, "api-port.json"), apiHint2);
604672
+ } catch {
604673
+ }
604674
+ }
604675
+ } catch (e2) {
604676
+ log22(` Nexus auto-recover: skipped (${e2.message.slice(0, 80)})
604677
+ `);
604678
+ }
604679
+ })();
604680
+ }
604269
604681
  try {
604270
604682
  adoptHandoffRuns();
604271
604683
  } catch (e2) {
@@ -604499,10 +604911,10 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
604499
604911
  const labels = Array.isArray(b.labels) ? b.labels : [];
604500
604912
  const mediaPath = typeof b.media_path === "string" ? b.media_path : void 0;
604501
604913
  const cwd4 = process.cwd();
604502
- const dbBase = join122(cwd4, ".oa");
604914
+ const dbBase = join123(cwd4, ".oa");
604503
604915
  const { EpisodeStore: EpisodeStore3, TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
604504
- const epStore = new EpisodeStore3(join122(dbBase, "memory.db"));
604505
- const kg = new TemporalGraph3(join122(dbBase, "kg.db"));
604916
+ const epStore = new EpisodeStore3(join123(dbBase, "memory.db"));
604917
+ const kg = new TemporalGraph3(join123(dbBase, "kg.db"));
604506
604918
  const meta = {};
604507
604919
  if (mediaPath) meta.media_path = mediaPath;
604508
604920
  const epId = epStore.insert({ modality, content: content || (mediaPath || ""), metadata: meta, toolName: "memory_ingest" });
@@ -604569,7 +604981,7 @@ async function handleEntitiesList(req2, res) {
604569
604981
  const type = url.searchParams.get("type") || "person";
604570
604982
  const limit = Math.max(1, Math.min(1e3, parseInt(url.searchParams.get("limit") || "100", 10)));
604571
604983
  const { TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
604572
- const kg = new TemporalGraph3(join122(process.cwd(), ".oa", "kg.db"));
604984
+ const kg = new TemporalGraph3(join123(process.cwd(), ".oa", "kg.db"));
604573
604985
  const nodes = kg.nodesByType(type, limit).map((n2) => ({ id: n2.id, text: n2.text, mentionCount: n2.mentionCount, firstSeen: n2.firstSeen, lastSeen: n2.lastSeen }));
604574
604986
  jsonResponse(res, 200, { object: "list", data: nodes });
604575
604987
  } catch (err) {
@@ -604591,7 +605003,7 @@ async function handleMemorySearch2(req2, res) {
604591
605003
  const wLex = typeof b.lexical_weight === "number" ? b.lexical_weight : 1;
604592
605004
  const wEmb = typeof b.embedding_weight === "number" ? b.embedding_weight : 1;
604593
605005
  const { EpisodeStore: EpisodeStore3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
604594
- const epStore = new EpisodeStore3(join122(process.cwd(), ".oa", "memory.db"));
605006
+ const epStore = new EpisodeStore3(join123(process.cwd(), ".oa", "memory.db"));
604595
605007
  const results = epStore.search({ query, modality, limit }, { queryEmbedding: qEmb, lexicalWeight: wLex, embeddingWeight: wEmb });
604596
605008
  jsonResponse(res, 200, { object: "list", data: results.map((e2) => ({ id: e2.id, modality: e2.modality, content: e2.content, timestamp: e2.timestamp })) });
604597
605009
  } catch (err) {
@@ -604708,11 +605120,11 @@ var init_serve = __esm({
604708
605120
 
604709
605121
  // packages/cli/src/tui/interactive.ts
604710
605122
  import { cwd } from "node:process";
604711
- import { resolve as resolve39, join as join123, dirname as dirname37, extname as extname12 } from "node:path";
605123
+ import { resolve as resolve39, join as join124, dirname as dirname37, extname as extname12 } from "node:path";
604712
605124
  import { createRequire as createRequire6 } from "node:module";
604713
605125
  import { fileURLToPath as fileURLToPath18 } from "node:url";
604714
- import { readFileSync as readFileSync87, writeFileSync as writeFileSync56, appendFileSync as appendFileSync8, rmSync as rmSync5, readdirSync as readdirSync37, mkdirSync as mkdirSync64 } from "node:fs";
604715
- import { existsSync as existsSync107 } from "node:fs";
605126
+ import { readFileSync as readFileSync87, writeFileSync as writeFileSync57, appendFileSync as appendFileSync8, rmSync as rmSync5, readdirSync as readdirSync37, mkdirSync as mkdirSync65 } from "node:fs";
605127
+ import { existsSync as existsSync108 } from "node:fs";
604716
605128
  import { execSync as execSync58 } from "node:child_process";
604717
605129
  import { homedir as homedir44 } from "node:os";
604718
605130
  function formatTimeAgo2(date) {
@@ -604730,12 +605142,12 @@ function getVersion4() {
604730
605142
  const require4 = createRequire6(import.meta.url);
604731
605143
  const thisDir = dirname37(fileURLToPath18(import.meta.url));
604732
605144
  const candidates = [
604733
- join123(thisDir, "..", "package.json"),
604734
- join123(thisDir, "..", "..", "package.json"),
604735
- join123(thisDir, "..", "..", "..", "package.json")
605145
+ join124(thisDir, "..", "package.json"),
605146
+ join124(thisDir, "..", "..", "package.json"),
605147
+ join124(thisDir, "..", "..", "..", "package.json")
604736
605148
  ];
604737
605149
  for (const pkgPath of candidates) {
604738
- if (existsSync107(pkgPath)) {
605150
+ if (existsSync108(pkgPath)) {
604739
605151
  const pkg = require4(pkgPath);
604740
605152
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
604741
605153
  return pkg.version ?? "0.0.0";
@@ -605541,14 +605953,14 @@ Meta-critique: quality ${meta.quality}/5, thorough: ${meta.thorough}`;
605541
605953
  function gatherMemorySnippets(root) {
605542
605954
  const snippets = [];
605543
605955
  const dirs = [
605544
- join123(root, ".oa", "memory"),
605545
- join123(root, ".open-agents", "memory")
605956
+ join124(root, ".oa", "memory"),
605957
+ join124(root, ".open-agents", "memory")
605546
605958
  ];
605547
605959
  for (const dir of dirs) {
605548
- if (!existsSync107(dir)) continue;
605960
+ if (!existsSync108(dir)) continue;
605549
605961
  try {
605550
605962
  for (const f2 of readdirSync37(dir).filter((f3) => f3.endsWith(".json"))) {
605551
- const data = JSON.parse(readFileSync87(join123(dir, f2), "utf-8"));
605963
+ const data = JSON.parse(readFileSync87(join124(dir, f2), "utf-8"));
605552
605964
  for (const val of Object.values(data)) {
605553
605965
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
605554
605966
  if (v.length > 10) snippets.push(v);
@@ -605702,8 +606114,8 @@ ${metabolismMemories}
605702
606114
  } catch {
605703
606115
  }
605704
606116
  try {
605705
- const archeFile = join123(repoRoot, ".oa", "arche", "variants.json");
605706
- if (existsSync107(archeFile)) {
606117
+ const archeFile = join124(repoRoot, ".oa", "arche", "variants.json");
606118
+ if (existsSync108(archeFile)) {
605707
606119
  const variants = JSON.parse(readFileSync87(archeFile, "utf8"));
605708
606120
  if (variants.length > 0) {
605709
606121
  let filtered = variants;
@@ -605876,8 +606288,8 @@ RULES:
605876
606288
  const compactionThreshold = Number.isFinite(envOverride) && envOverride > 0 ? envOverride : modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
605877
606289
  let identityInjection = "";
605878
606290
  try {
605879
- const ikStateFile = join123(repoRoot, ".oa", "identity", "self-state.json");
605880
- if (existsSync107(ikStateFile)) {
606291
+ const ikStateFile = join124(repoRoot, ".oa", "identity", "self-state.json");
606292
+ if (existsSync108(ikStateFile)) {
605881
606293
  const selfState = JSON.parse(readFileSync87(ikStateFile, "utf8"));
605882
606294
  const lines = [
605883
606295
  `[Identity State v${selfState.version}]`,
@@ -606740,13 +607152,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606740
607152
  });
606741
607153
  }
606742
607154
  try {
606743
- const ikDir = join123(repoRoot, ".oa", "identity");
606744
- const ikFile = join123(ikDir, "self-state.json");
607155
+ const ikDir = join124(repoRoot, ".oa", "identity");
607156
+ const ikFile = join124(ikDir, "self-state.json");
606745
607157
  let ikState;
606746
- if (existsSync107(ikFile)) {
607158
+ if (existsSync108(ikFile)) {
606747
607159
  ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
606748
607160
  } else {
606749
- mkdirSync64(ikDir, { recursive: true });
607161
+ mkdirSync65(ikDir, { recursive: true });
606750
607162
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
606751
607163
  ikState = {
606752
607164
  self_id: `oa-${machineId}`,
@@ -606802,7 +607214,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606802
607214
  }
606803
607215
  ikState.session_count = (ikState.session_count || 0) + 1;
606804
607216
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
606805
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
607217
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
606806
607218
  } catch (ikErr) {
606807
607219
  try {
606808
607220
  console.error("[IK-OBSERVE]", ikErr);
@@ -606821,8 +607233,8 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606821
607233
  } else {
606822
607234
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
606823
607235
  try {
606824
- const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
606825
- if (existsSync107(ikFile)) {
607236
+ const ikFile = join124(repoRoot, ".oa", "identity", "self-state.json");
607237
+ if (existsSync108(ikFile)) {
606826
607238
  const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
606827
607239
  if (!ikState.stats) ikState.stats = { queries_served: 0 };
606828
607240
  ikState.stats.queries_served = (ikState.stats.queries_served || 0) + 1;
@@ -606834,7 +607246,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606834
607246
  if (ikState.version_history.length > 200) ikState.version_history = ikState.version_history.slice(-200);
606835
607247
  ikState.session_count = (ikState.session_count || 0) + 1;
606836
607248
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
606837
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
607249
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
606838
607250
  }
606839
607251
  } catch {
606840
607252
  }
@@ -607079,9 +607491,9 @@ async function startInteractive(config, repoPath) {
607079
607491
  process.stdin.pause();
607080
607492
  }
607081
607493
  try {
607082
- const oaDir = join123(repoRoot, ".oa");
607083
- const nexusPidFile = join123(oaDir, "nexus", "daemon.pid");
607084
- if (existsSync107(nexusPidFile)) {
607494
+ const oaDir = join124(repoRoot, ".oa");
607495
+ const nexusPidFile = join124(oaDir, "nexus", "daemon.pid");
607496
+ if (existsSync108(nexusPidFile)) {
607085
607497
  const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
607086
607498
  if (pid > 0) {
607087
607499
  try {
@@ -607742,7 +608154,7 @@ ${result.summary}`
607742
608154
  let p2pGateway = null;
607743
608155
  let peerMesh = null;
607744
608156
  let inferenceRouter = null;
607745
- const secretVault = new SecretVault(join123(repoRoot, ".oa", "vault.enc"));
608157
+ const secretVault = new SecretVault(join124(repoRoot, ".oa", "vault.enc"));
607746
608158
  let adminSessionKey = null;
607747
608159
  const callSubAgents = /* @__PURE__ */ new Map();
607748
608160
  const streamRenderer = new StreamRenderer();
@@ -607973,12 +608385,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
607973
608385
  const hits = allCompletions.filter((c9) => c9.toLowerCase().startsWith(lower));
607974
608386
  return [hits, line];
607975
608387
  }
607976
- const HISTORY_DIR = join123(homedir44(), ".open-agents");
607977
- const HISTORY_FILE = join123(HISTORY_DIR, "repl-history");
608388
+ const HISTORY_DIR = join124(homedir44(), ".open-agents");
608389
+ const HISTORY_FILE = join124(HISTORY_DIR, "repl-history");
607978
608390
  const MAX_HISTORY_LINES = 500;
607979
608391
  let savedHistory = [];
607980
608392
  try {
607981
- if (existsSync107(HISTORY_FILE)) {
608393
+ if (existsSync108(HISTORY_FILE)) {
607982
608394
  const raw = readFileSync87(HISTORY_FILE, "utf8").trim();
607983
608395
  if (raw) savedHistory = raw.split("\n").reverse();
607984
608396
  }
@@ -608126,12 +608538,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608126
608538
  function persistHistoryLine(line) {
608127
608539
  if (!line.trim()) return;
608128
608540
  try {
608129
- mkdirSync64(HISTORY_DIR, { recursive: true });
608541
+ mkdirSync65(HISTORY_DIR, { recursive: true });
608130
608542
  appendFileSync8(HISTORY_FILE, line + "\n", "utf8");
608131
608543
  if (Math.random() < 0.02) {
608132
608544
  const all2 = readFileSync87(HISTORY_FILE, "utf8").trim().split("\n");
608133
608545
  if (all2.length > MAX_HISTORY_LINES) {
608134
- writeFileSync56(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
608546
+ writeFileSync57(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
608135
608547
  }
608136
608548
  }
608137
608549
  } catch {
@@ -608316,10 +608728,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608316
608728
  const { unlinkSync: _rmStale } = await import("node:fs");
608317
608729
  const { homedir: _hdir } = await import("node:os");
608318
608730
  for (const dp of [
608319
- join123(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
608320
- join123(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
608731
+ join124(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
608732
+ join124(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
608321
608733
  ]) {
608322
- if (existsSync107(dp)) try {
608734
+ if (existsSync108(dp)) try {
608323
608735
  _rmStale(dp);
608324
608736
  } catch {
608325
608737
  }
@@ -608330,8 +608742,8 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608330
608742
  const autoNexus = new NexusTool(repoRoot);
608331
608743
  const _registerNexusDaemon = () => {
608332
608744
  try {
608333
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
608334
- if (existsSync107(nexusPidFile)) {
608745
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
608746
+ if (existsSync108(nexusPidFile)) {
608335
608747
  const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
608336
608748
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
608337
608749
  registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
@@ -608389,7 +608801,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608389
608801
  } catch {
608390
608802
  }
608391
608803
  try {
608392
- const oaDir = join123(repoRoot, ".oa");
608804
+ const oaDir = join124(repoRoot, ".oa");
608393
608805
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
608394
608806
  onInfo: (msg) => writeContent(() => renderInfo2(msg)),
608395
608807
  onError: (msg) => writeContent(() => renderWarning2(msg))
@@ -608421,7 +608833,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608421
608833
  } catch {
608422
608834
  }
608423
608835
  try {
608424
- const oaDir = join123(repoRoot, ".oa");
608836
+ const oaDir = join124(repoRoot, ".oa");
608425
608837
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
608426
608838
  onInfo: (msg) => writeContent(() => renderInfo2(msg)),
608427
608839
  onError: (msg) => writeContent(() => renderWarning2(msg))
@@ -608462,10 +608874,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608462
608874
  }
608463
608875
  try {
608464
608876
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
608465
- const globalNamePath = join123(_hd(), ".open-agents", "agent-name");
608877
+ const globalNamePath = join124(_hd(), ".open-agents", "agent-name");
608466
608878
  let agName = "";
608467
608879
  try {
608468
- if (existsSync107(globalNamePath)) agName = readFileSync87(globalNamePath, "utf8").trim();
608880
+ if (existsSync108(globalNamePath)) agName = readFileSync87(globalNamePath, "utf8").trim();
608469
608881
  } catch {
608470
608882
  }
608471
608883
  if (!agName) {
@@ -608494,10 +608906,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608494
608906
  }
608495
608907
  if (!ollamaAlive) {
608496
608908
  try {
608497
- const savedSponsorsPath = join123(repoRoot, ".oa", "sponsor", "known-sponsors.json");
608909
+ const savedSponsorsPath = join124(repoRoot, ".oa", "sponsor", "known-sponsors.json");
608498
608910
  let savedSponsors = [];
608499
608911
  try {
608500
- if (existsSync107(savedSponsorsPath)) {
608912
+ if (existsSync108(savedSponsorsPath)) {
608501
608913
  savedSponsors = JSON.parse(readFileSync87(savedSponsorsPath, "utf8"));
608502
608914
  const oneHourAgo = Date.now() - 36e5;
608503
608915
  savedSponsors = savedSponsors.filter((s2) => (s2.lastVerified || 0) > oneHourAgo);
@@ -609590,10 +610002,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609590
610002
  if (name10 === "voice_list_files") {
609591
610003
  const baseDir = String(args?.dir ?? ".");
609592
610004
  const { readdirSync: readdirSync39, statSync: statSync36 } = __require("node:fs");
609593
- const { join: join128, resolve: resolve43 } = __require("node:path");
609594
- const base3 = baseDir.startsWith("/") ? baseDir : resolve43(join128(repoRoot, baseDir));
610005
+ const { join: join129, resolve: resolve43 } = __require("node:path");
610006
+ const base3 = baseDir.startsWith("/") ? baseDir : resolve43(join129(repoRoot, baseDir));
609595
610007
  const items = readdirSync39(base3).slice(0, 200).map((f2) => {
609596
- const s2 = statSync36(join128(base3, f2));
610008
+ const s2 = statSync36(join129(base3, f2));
609597
610009
  return { name: f2, dir: s2.isDirectory(), size: s2.size };
609598
610010
  });
609599
610011
  return JSON.stringify({ dir: base3, items }, null, 2);
@@ -609681,7 +610093,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609681
610093
  kind,
609682
610094
  targetUrl,
609683
610095
  authKey,
609684
- stateDir: join123(repoRoot, ".oa"),
610096
+ stateDir: join124(repoRoot, ".oa"),
609685
610097
  passthrough: passthrough ?? false,
609686
610098
  loadbalance: loadbalance ?? false,
609687
610099
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -609727,7 +610139,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609727
610139
  await tunnelGateway.stop();
609728
610140
  tunnelGateway = null;
609729
610141
  }
609730
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join123(repoRoot, ".oa") });
610142
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join124(repoRoot, ".oa") });
609731
610143
  newTunnel.on("stats", (stats) => {
609732
610144
  statusBar.setExposeStatus({
609733
610145
  status: stats.status,
@@ -609748,14 +610160,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609748
610160
  throw err;
609749
610161
  }
609750
610162
  },
609751
- async exposeStop(which) {
609752
- if (!which || which === "tunnel") {
610163
+ async exposeStop(which2) {
610164
+ if (!which2 || which2 === "tunnel") {
609753
610165
  if (tunnelGateway) {
609754
610166
  await tunnelGateway.stop();
609755
610167
  tunnelGateway = null;
609756
610168
  }
609757
610169
  }
609758
- if (!which || which === "libp2p") {
610170
+ if (!which2 || which2 === "libp2p") {
609759
610171
  if (p2pGateway) {
609760
610172
  await p2pGateway.stop();
609761
610173
  p2pGateway = null;
@@ -609814,8 +610226,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609814
610226
  });
609815
610227
  if (!result.success) throw new Error(result.error || "Connect failed");
609816
610228
  try {
609817
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
609818
- if (existsSync107(nexusPidFile)) {
610229
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
610230
+ if (existsSync108(nexusPidFile)) {
609819
610231
  const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
609820
610232
  if (pid > 0) {
609821
610233
  registry2.register({
@@ -610004,9 +610416,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610004
610416
  writeContent(() => renderInfo2(`Killed ${bgKilled} background task(s).`));
610005
610417
  }
610006
610418
  try {
610007
- const nexusDir = join123(repoRoot, OA_DIR, "nexus");
610008
- const pidFile = join123(nexusDir, "daemon.pid");
610009
- if (existsSync107(pidFile)) {
610419
+ const nexusDir = join124(repoRoot, OA_DIR, "nexus");
610420
+ const pidFile = join124(nexusDir, "daemon.pid");
610421
+ if (existsSync108(pidFile)) {
610010
610422
  const pid = parseInt(readFileSync87(pidFile, "utf8").trim(), 10);
610011
610423
  if (pid > 0) {
610012
610424
  try {
@@ -610029,11 +610441,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610029
610441
  } catch {
610030
610442
  }
610031
610443
  try {
610032
- const voiceDir2 = join123(homedir44(), ".open-agents", "voice");
610444
+ const voiceDir2 = join124(homedir44(), ".open-agents", "voice");
610033
610445
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
610034
610446
  for (const pf of voicePidFiles) {
610035
- const pidPath = join123(voiceDir2, pf);
610036
- if (existsSync107(pidPath)) {
610447
+ const pidPath = join124(voiceDir2, pf);
610448
+ if (existsSync108(pidPath)) {
610037
610449
  try {
610038
610450
  const pid = parseInt(readFileSync87(pidPath, "utf8").trim(), 10);
610039
610451
  if (pid > 0) {
@@ -610059,8 +610471,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610059
610471
  execSync58(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
610060
610472
  } catch {
610061
610473
  }
610062
- const oaPath = join123(repoRoot, OA_DIR);
610063
- if (existsSync107(oaPath)) {
610474
+ const oaPath = join124(repoRoot, OA_DIR);
610475
+ if (existsSync108(oaPath)) {
610064
610476
  let deleted = false;
610065
610477
  for (let attempt = 0; attempt < 3; attempt++) {
610066
610478
  try {
@@ -610144,18 +610556,18 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610144
610556
  try {
610145
610557
  const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
610146
610558
  if (isPersonaPlexRunning2()) {
610147
- const ppPidFile = join123(homedir44(), ".open-agents", "voice", "personaplex", "daemon.pid");
610148
- const ppPortFile = join123(homedir44(), ".open-agents", "voice", "personaplex", "daemon.port");
610149
- if (existsSync107(ppPidFile)) {
610559
+ const ppPidFile = join124(homedir44(), ".open-agents", "voice", "personaplex", "daemon.pid");
610560
+ const ppPortFile = join124(homedir44(), ".open-agents", "voice", "personaplex", "daemon.port");
610561
+ if (existsSync108(ppPidFile)) {
610150
610562
  const ppPid = parseInt(readFileSync87(ppPidFile, "utf8").trim(), 10);
610151
- const ppPort = existsSync107(ppPortFile) ? parseInt(readFileSync87(ppPortFile, "utf8").trim(), 10) : void 0;
610563
+ const ppPort = existsSync108(ppPortFile) ? parseInt(readFileSync87(ppPortFile, "utf8").trim(), 10) : void 0;
610152
610564
  if (ppPid > 0 && !registry2.daemons.has("PersonaPlex")) {
610153
610565
  registry2.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
610154
610566
  }
610155
610567
  }
610156
610568
  }
610157
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
610158
- if (existsSync107(nexusPidFile)) {
610569
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
610570
+ if (existsSync108(nexusPidFile)) {
610159
610571
  const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
610160
610572
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
610161
610573
  try {
@@ -610523,9 +610935,9 @@ Execute this skill now. Follow the behavioral guidance above.`;
610523
610935
  }
610524
610936
  }
610525
610937
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
610526
- const isImage = isImagePath(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
610527
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
610528
- const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
610938
+ const isImage = isImagePath(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610939
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610940
+ const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610529
610941
  if (activeTask) {
610530
610942
  if (activeTask.runner.isPaused) {
610531
610943
  activeTask.runner.resume();
@@ -611112,13 +611524,13 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611112
611524
  const handle2 = startTask(task, config, repoRoot);
611113
611525
  await handle2.promise;
611114
611526
  try {
611115
- const ikDir = join123(repoRoot, ".oa", "identity");
611116
- const ikFile = join123(ikDir, "self-state.json");
611527
+ const ikDir = join124(repoRoot, ".oa", "identity");
611528
+ const ikFile = join124(ikDir, "self-state.json");
611117
611529
  let ikState;
611118
- if (existsSync107(ikFile)) {
611530
+ if (existsSync108(ikFile)) {
611119
611531
  ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
611120
611532
  } else {
611121
- mkdirSync64(ikDir, { recursive: true });
611533
+ mkdirSync65(ikDir, { recursive: true });
611122
611534
  ikState = {
611123
611535
  self_id: `oa-${Date.now().toString(36)}`,
611124
611536
  version: 1,
@@ -611140,7 +611552,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611140
611552
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
611141
611553
  ikState.session_count = (ikState.session_count || 0) + 1;
611142
611554
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
611143
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
611555
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
611144
611556
  } catch (ikErr) {
611145
611557
  }
611146
611558
  try {
@@ -611153,11 +611565,11 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611153
611565
  );
611154
611566
  } catch {
611155
611567
  try {
611156
- const archeDir = join123(repoRoot, ".oa", "arche");
611157
- const archeFile = join123(archeDir, "variants.json");
611568
+ const archeDir = join124(repoRoot, ".oa", "arche");
611569
+ const archeFile = join124(archeDir, "variants.json");
611158
611570
  let variants = [];
611159
611571
  try {
611160
- if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611572
+ if (existsSync108(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611161
611573
  } catch {
611162
611574
  }
611163
611575
  variants.push({
@@ -611171,14 +611583,14 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611171
611583
  tags: ["general"]
611172
611584
  });
611173
611585
  if (variants.length > 50) variants = variants.slice(-50);
611174
- mkdirSync64(archeDir, { recursive: true });
611175
- writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
611586
+ mkdirSync65(archeDir, { recursive: true });
611587
+ writeFileSync57(archeFile, JSON.stringify(variants, null, 2));
611176
611588
  } catch {
611177
611589
  }
611178
611590
  }
611179
611591
  try {
611180
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611181
- if (existsSync107(metaFile)) {
611592
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611593
+ if (existsSync108(metaFile)) {
611182
611594
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611183
611595
  const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
611184
611596
  let updated = false;
@@ -611190,7 +611602,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611190
611602
  updated = true;
611191
611603
  }
611192
611604
  if (updated) {
611193
- writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
611605
+ writeFileSync57(metaFile, JSON.stringify(store2, null, 2));
611194
611606
  }
611195
611607
  }
611196
611608
  } catch {
@@ -611243,9 +611655,9 @@ Rules:
611243
611655
  try {
611244
611656
  const { initDb: initDb2 } = __require("@open-agents/memory");
611245
611657
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
611246
- const dbDir = join123(repoRoot, ".oa", "memory");
611247
- mkdirSync64(dbDir, { recursive: true });
611248
- const db = initDb2(join123(dbDir, "structured.db"));
611658
+ const dbDir = join124(repoRoot, ".oa", "memory");
611659
+ mkdirSync65(dbDir, { recursive: true });
611660
+ const db = initDb2(join124(dbDir, "structured.db"));
611249
611661
  const memStore = new ProceduralMemoryStore2(db);
611250
611662
  memStore.createWithEmbedding({
611251
611663
  content: content.slice(0, 600),
@@ -611260,11 +611672,11 @@ Rules:
611260
611672
  db.close();
611261
611673
  } catch {
611262
611674
  }
611263
- const metaDir = join123(repoRoot, ".oa", "memory", "metabolism");
611264
- const storeFile = join123(metaDir, "store.json");
611675
+ const metaDir = join124(repoRoot, ".oa", "memory", "metabolism");
611676
+ const storeFile = join124(metaDir, "store.json");
611265
611677
  let store2 = [];
611266
611678
  try {
611267
- if (existsSync107(storeFile)) store2 = JSON.parse(readFileSync87(storeFile, "utf8"));
611679
+ if (existsSync108(storeFile)) store2 = JSON.parse(readFileSync87(storeFile, "utf8"));
611268
611680
  } catch {
611269
611681
  }
611270
611682
  store2.push({
@@ -611279,25 +611691,25 @@ Rules:
611279
611691
  accessCount: 0
611280
611692
  });
611281
611693
  if (store2.length > 100) store2 = store2.slice(-100);
611282
- mkdirSync64(metaDir, { recursive: true });
611283
- writeFileSync56(storeFile, JSON.stringify(store2, null, 2));
611694
+ mkdirSync65(metaDir, { recursive: true });
611695
+ writeFileSync57(storeFile, JSON.stringify(store2, null, 2));
611284
611696
  }
611285
611697
  }
611286
611698
  } catch {
611287
611699
  }
611288
611700
  try {
611289
- const cohereSettingsFile = join123(repoRoot, ".oa", "settings.json");
611701
+ const cohereSettingsFile = join124(repoRoot, ".oa", "settings.json");
611290
611702
  let cohereActive = false;
611291
611703
  try {
611292
- if (existsSync107(cohereSettingsFile)) {
611704
+ if (existsSync108(cohereSettingsFile)) {
611293
611705
  const settings = JSON.parse(readFileSync87(cohereSettingsFile, "utf8"));
611294
611706
  cohereActive = settings.cohere === true;
611295
611707
  }
611296
611708
  } catch {
611297
611709
  }
611298
611710
  if (cohereActive) {
611299
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611300
- if (existsSync107(metaFile)) {
611711
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611712
+ if (existsSync108(metaFile)) {
611301
611713
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611302
611714
  const latest = store2.filter((m2) => m2.sourceTrace === "trajectory-extraction" || m2.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
611303
611715
  if (latest && latest.scores?.confidence >= 0.6) {
@@ -611323,17 +611735,17 @@ Rules:
611323
611735
  }
611324
611736
  } catch (err) {
611325
611737
  try {
611326
- const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
611327
- if (existsSync107(ikFile)) {
611738
+ const ikFile = join124(repoRoot, ".oa", "identity", "self-state.json");
611739
+ if (existsSync108(ikFile)) {
611328
611740
  const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
611329
611741
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
611330
611742
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
611331
611743
  ikState.session_count = (ikState.session_count || 0) + 1;
611332
611744
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
611333
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
611745
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
611334
611746
  }
611335
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611336
- if (existsSync107(metaFile)) {
611747
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611748
+ if (existsSync108(metaFile)) {
611337
611749
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611338
611750
  const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
611339
611751
  for (const item of surfaced) {
@@ -611342,14 +611754,14 @@ Rules:
611342
611754
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
611343
611755
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
611344
611756
  }
611345
- writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
611757
+ writeFileSync57(metaFile, JSON.stringify(store2, null, 2));
611346
611758
  }
611347
611759
  try {
611348
- const archeDir = join123(repoRoot, ".oa", "arche");
611349
- const archeFile = join123(archeDir, "variants.json");
611760
+ const archeDir = join124(repoRoot, ".oa", "arche");
611761
+ const archeFile = join124(archeDir, "variants.json");
611350
611762
  let variants = [];
611351
611763
  try {
611352
- if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611764
+ if (existsSync108(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611353
611765
  } catch {
611354
611766
  }
611355
611767
  variants.push({
@@ -611363,8 +611775,8 @@ Rules:
611363
611775
  tags: ["general"]
611364
611776
  });
611365
611777
  if (variants.length > 50) variants = variants.slice(-50);
611366
- mkdirSync64(archeDir, { recursive: true });
611367
- writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
611778
+ mkdirSync65(archeDir, { recursive: true });
611779
+ writeFileSync57(archeFile, JSON.stringify(variants, null, 2));
611368
611780
  } catch {
611369
611781
  }
611370
611782
  } catch {
@@ -611452,14 +611864,14 @@ __export(run_exports, {
611452
611864
  statusCommand: () => statusCommand
611453
611865
  });
611454
611866
  import { resolve as resolve40 } from "node:path";
611455
- import { spawn as spawn26 } from "node:child_process";
611456
- import { mkdirSync as mkdirSync65, writeFileSync as writeFileSync57, readFileSync as readFileSync88, readdirSync as readdirSync38, existsSync as existsSync108 } from "node:fs";
611867
+ import { spawn as spawn27 } from "node:child_process";
611868
+ import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58, readFileSync as readFileSync88, readdirSync as readdirSync38, existsSync as existsSync109 } from "node:fs";
611457
611869
  import { randomBytes as randomBytes24 } from "node:crypto";
611458
- import { join as join124 } from "node:path";
611870
+ import { join as join125 } from "node:path";
611459
611871
  function jobsDir2(repoPath) {
611460
611872
  const root = resolve40(repoPath ?? process.cwd());
611461
- const dir = join124(root, ".oa", "jobs");
611462
- mkdirSync65(dir, { recursive: true });
611873
+ const dir = join125(root, ".oa", "jobs");
611874
+ mkdirSync66(dir, { recursive: true });
611463
611875
  return dir;
611464
611876
  }
611465
611877
  async function runCommand(opts, config) {
@@ -611565,7 +611977,7 @@ async function runBackground(task, config, opts) {
611565
611977
  const oaBin = process.argv[1] || "oa";
611566
611978
  const args = [task, "--json"];
611567
611979
  if (config.model) args.push("--model", config.model);
611568
- const child = spawn26(process.execPath, [oaBin, ...args], {
611980
+ const child = spawn27(process.execPath, [oaBin, ...args], {
611569
611981
  cwd: repoRoot,
611570
611982
  env: { ...process.env, OA_JOB_ID: id },
611571
611983
  stdio: ["ignore", "pipe", "pipe"],
@@ -611581,7 +611993,7 @@ async function runBackground(task, config, opts) {
611581
611993
  }
611582
611994
  });
611583
611995
  job.pid = child.pid ?? 0;
611584
- writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
611996
+ writeFileSync58(join125(dir, `${id}.json`), JSON.stringify(job, null, 2));
611585
611997
  let output = "";
611586
611998
  child.stdout?.on("data", (chunk) => {
611587
611999
  output += chunk.toString();
@@ -611597,7 +612009,7 @@ async function runBackground(task, config, opts) {
611597
612009
  job.summary = result.summary;
611598
612010
  job.durationMs = result.durationMs;
611599
612011
  job.error = result.error;
611600
- writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
612012
+ writeFileSync58(join125(dir, `${id}.json`), JSON.stringify(job, null, 2));
611601
612013
  } catch {
611602
612014
  }
611603
612015
  });
@@ -611613,8 +612025,8 @@ async function runBackground(task, config, opts) {
611613
612025
  }
611614
612026
  function statusCommand(jobId, repoPath) {
611615
612027
  const dir = jobsDir2(repoPath);
611616
- const file = join124(dir, `${jobId}.json`);
611617
- if (!existsSync108(file)) {
612028
+ const file = join125(dir, `${jobId}.json`);
612029
+ if (!existsSync109(file)) {
611618
612030
  console.error(`Job not found: ${jobId}`);
611619
612031
  console.log(`Available jobs: oa jobs`);
611620
612032
  process.exit(1);
@@ -611640,7 +612052,7 @@ function jobsCommand(repoPath) {
611640
612052
  console.log("Jobs:");
611641
612053
  for (const file of files) {
611642
612054
  try {
611643
- const job = JSON.parse(readFileSync88(join124(dir, file), "utf-8"));
612055
+ const job = JSON.parse(readFileSync88(join125(dir, file), "utf-8"));
611644
612056
  const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
611645
612057
  const runtime = job.completedAt ? `${((new Date(job.completedAt).getTime() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s` : `${((Date.now() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s`;
611646
612058
  const cleanListTask = cleanForStorage(job.task) || job.task;
@@ -611664,13 +612076,13 @@ __export(index_repo_exports, {
611664
612076
  indexRepoCommand: () => indexRepoCommand
611665
612077
  });
611666
612078
  import { resolve as resolve41 } from "node:path";
611667
- import { existsSync as existsSync109, statSync as statSync35 } from "node:fs";
612079
+ import { existsSync as existsSync110, statSync as statSync35 } from "node:fs";
611668
612080
  import { cwd as cwd2 } from "node:process";
611669
612081
  async function indexRepoCommand(opts, _config3) {
611670
612082
  const repoRoot = resolve41(opts.repoPath ?? cwd2());
611671
612083
  printHeader("Index Repository");
611672
612084
  printInfo(`Indexing: ${repoRoot}`);
611673
- if (!existsSync109(repoRoot)) {
612085
+ if (!existsSync110(repoRoot)) {
611674
612086
  printError(`Path does not exist: ${repoRoot}`);
611675
612087
  process.exit(1);
611676
612088
  }
@@ -611922,7 +612334,7 @@ var config_exports2 = {};
611922
612334
  __export(config_exports2, {
611923
612335
  configCommand: () => configCommand
611924
612336
  });
611925
- import { join as join125, resolve as resolve42 } from "node:path";
612337
+ import { join as join126, resolve as resolve42 } from "node:path";
611926
612338
  import { homedir as homedir45 } from "node:os";
611927
612339
  import { cwd as cwd3 } from "node:process";
611928
612340
  function redactIfSensitive(key, value2) {
@@ -612004,7 +612416,7 @@ function handleShow(opts, config) {
612004
612416
  }
612005
612417
  }
612006
612418
  printSection("Config File");
612007
- printInfo(`~/.open-agents/config.json (${join125(homedir45(), ".open-agents", "config.json")})`);
612419
+ printInfo(`~/.open-agents/config.json (${join126(homedir45(), ".open-agents", "config.json")})`);
612008
612420
  printSection("Priority Chain");
612009
612421
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
612010
612422
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -612043,7 +612455,7 @@ function handleSet(opts, _config3) {
612043
612455
  const coerced = coerceForSettings(key, value2);
612044
612456
  saveProjectSettings(repoRoot, { [key]: coerced });
612045
612457
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value2)}`);
612046
- printInfo(`Saved to ${join125(repoRoot, ".oa", "settings.json")}`);
612458
+ printInfo(`Saved to ${join126(repoRoot, ".oa", "settings.json")}`);
612047
612459
  printInfo("This override applies only when running in this workspace.");
612048
612460
  } catch (err) {
612049
612461
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -612226,9 +612638,9 @@ var eval_exports = {};
612226
612638
  __export(eval_exports, {
612227
612639
  evalCommand: () => evalCommand
612228
612640
  });
612229
- import { tmpdir as tmpdir21 } from "node:os";
612230
- import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58 } from "node:fs";
612231
- import { join as join126 } from "node:path";
612641
+ import { tmpdir as tmpdir22 } from "node:os";
612642
+ import { mkdirSync as mkdirSync67, writeFileSync as writeFileSync59 } from "node:fs";
612643
+ import { join as join127 } from "node:path";
612232
612644
  async function evalCommand(opts, config) {
612233
612645
  const suiteName = opts.suite ?? "basic";
612234
612646
  const suite = SUITES[suiteName];
@@ -612357,10 +612769,10 @@ async function evalCommand(opts, config) {
612357
612769
  process.exit(failed > 0 ? 1 : 0);
612358
612770
  }
612359
612771
  function createTempEvalRepo() {
612360
- const dir = join126(tmpdir21(), `open-agents-eval-${Date.now()}`);
612361
- mkdirSync66(dir, { recursive: true });
612362
- writeFileSync58(
612363
- join126(dir, "package.json"),
612772
+ const dir = join127(tmpdir22(), `open-agents-eval-${Date.now()}`);
612773
+ mkdirSync67(dir, { recursive: true });
612774
+ writeFileSync59(
612775
+ join127(dir, "package.json"),
612364
612776
  JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
612365
612777
  "utf8"
612366
612778
  );
@@ -612424,7 +612836,7 @@ init_typed_node_events();
612424
612836
  import { parseArgs as nodeParseArgs2 } from "node:util";
612425
612837
  import { createRequire as createRequire7 } from "node:module";
612426
612838
  import { fileURLToPath as fileURLToPath19 } from "node:url";
612427
- import { dirname as dirname38, join as join127 } from "node:path";
612839
+ import { dirname as dirname38, join as join128 } from "node:path";
612428
612840
 
612429
612841
  // packages/cli/src/cli.ts
612430
612842
  init_typed_node_events();
@@ -612564,7 +612976,7 @@ init_output();
612564
612976
  function getVersion5() {
612565
612977
  try {
612566
612978
  const require4 = createRequire7(import.meta.url);
612567
- const pkgPath = join127(dirname38(fileURLToPath19(import.meta.url)), "..", "package.json");
612979
+ const pkgPath = join128(dirname38(fileURLToPath19(import.meta.url)), "..", "package.json");
612568
612980
  const pkg = require4(pkgPath);
612569
612981
  return pkg.version;
612570
612982
  } catch {
@@ -612753,9 +613165,9 @@ async function main() {
612753
613165
  const mode = process.argv[process.argv.indexOf("--self-test") + 1] || "crossmodal";
612754
613166
  if (mode === "crossmodal") {
612755
613167
  process.stdout.write("Running crossmodal smoke tests...\n");
612756
- const { spawn: spawn27 } = await import("node:child_process");
613168
+ const { spawn: spawn28 } = await import("node:child_process");
612757
613169
  const run = (file) => new Promise((resolve43, reject) => {
612758
- const p2 = spawn27(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
613170
+ const p2 = spawn28(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
612759
613171
  p2.stdout.on("data", (d2) => process.stdout.write(d2));
612760
613172
  p2.stderr.on("data", (d2) => process.stdout.write(d2));
612761
613173
  onChildExit(p2, (code8) => code8 === 0 ? resolve43() : reject(new Error(`${file} exited ${code8}`)));
@@ -612878,12 +613290,12 @@ function crashLog(label, err) {
612878
613290
  const logLine = `[${timestamp}] ${label}: ${msg}
612879
613291
  `;
612880
613292
  try {
612881
- const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync67 } = __require("node:fs");
612882
- const { join: join128 } = __require("node:path");
613293
+ const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync68 } = __require("node:fs");
613294
+ const { join: join129 } = __require("node:path");
612883
613295
  const { homedir: homedir46 } = __require("node:os");
612884
- const logDir = join128(homedir46(), ".open-agents");
612885
- mkdirSync67(logDir, { recursive: true });
612886
- appendFileSync9(join128(logDir, "crash.log"), logLine);
613296
+ const logDir = join129(homedir46(), ".open-agents");
613297
+ mkdirSync68(logDir, { recursive: true });
613298
+ appendFileSync9(join129(logDir, "crash.log"), logLine);
612887
613299
  } catch {
612888
613300
  }
612889
613301
  try {