open-agents-ai 0.187.536 → 0.187.538

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,136 @@ function resolveLocalPeerId() {
587107
587232
  _peerIdScanCache = { ts: now, result: scanResult };
587108
587233
  return scanResult;
587109
587234
  }
587235
+ function locateTorScript(filename) {
587236
+ const candidates = [
587237
+ // npm-installed layout: scripts get copied to dist/scripts/tor/ by
587238
+ // scripts/build-publish.mjs. __dirname at runtime points at dist/api.
587239
+ join119(__dirname, "..", "scripts", "tor", filename),
587240
+ // Workspace dev: cli package's source tree.
587241
+ join119(__dirname, "..", "..", "scripts", "tor", filename),
587242
+ // Workspace dev (from cwd at repo root):
587243
+ join119(process.cwd(), "packages", "cli", "scripts", "tor", filename),
587244
+ join119(process.cwd(), "scripts", "tor", filename)
587245
+ ];
587246
+ for (const p2 of candidates) {
587247
+ if (existsSync103(p2)) return p2;
587248
+ }
587249
+ try {
587250
+ const { execSync: execSync59 } = __require("node:child_process");
587251
+ const root = execSync59("npm root -g", { encoding: "utf-8", timeout: 5e3 }).trim();
587252
+ const p2 = join119(root, "open-agents-ai", "dist", "scripts", "tor", filename);
587253
+ if (existsSync103(p2)) return p2;
587254
+ } catch {
587255
+ }
587256
+ return null;
587257
+ }
587258
+ async function handleTorStatus(ctx3) {
587259
+ const { res } = ctx3;
587260
+ const { getLocalOnion: getLocalOnion2, torIsReachable: torIsReachable2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
587261
+ const { detectSudoHelper: detectSudoHelper2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587262
+ const onion = getLocalOnion2();
587263
+ const reachable = await torIsReachable2();
587264
+ sendJson(res, 200, {
587265
+ onion,
587266
+ socks5_reachable: reachable,
587267
+ sudo_helper: detectSudoHelper2()
587268
+ });
587269
+ return true;
587270
+ }
587271
+ async function handleTorEnable(ctx3) {
587272
+ const { req: req2, res, requestId } = ctx3;
587273
+ const reqAuth = req2;
587274
+ if (reqAuth._authScope !== "admin") {
587275
+ sendProblem(res, problemDetails({
587276
+ type: P.forbidden,
587277
+ status: 403,
587278
+ title: "Admin scope required",
587279
+ detail: "Tor setup requires elevated privileges; only admin keys can request it.",
587280
+ instance: requestId
587281
+ }));
587282
+ return true;
587283
+ }
587284
+ const { getLocalOnion: getLocalOnion2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
587285
+ if (getLocalOnion2()) {
587286
+ sendJson(res, 409, {
587287
+ status: "already_configured",
587288
+ onion: getLocalOnion2(),
587289
+ _note: "Tor hidden service already exists. Use /v1/tor/disable to remove."
587290
+ });
587291
+ return true;
587292
+ }
587293
+ const scriptPath2 = locateTorScript("tor_setup.sh");
587294
+ if (!scriptPath2) {
587295
+ sendProblem(res, problemDetails({
587296
+ type: P.internalError,
587297
+ status: 500,
587298
+ title: "tor_setup.sh not found",
587299
+ detail: "Could not locate the bundled Tor setup script.",
587300
+ instance: requestId
587301
+ }));
587302
+ return true;
587303
+ }
587304
+ const { detectSudoHelper: detectSudoHelper2, runGraphicalSudo: runGraphicalSudo2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587305
+ const helper = detectSudoHelper2();
587306
+ if (!helper) {
587307
+ sendProblem(res, problemDetails({
587308
+ type: P.internalError,
587309
+ status: 503,
587310
+ title: "No graphical sudo helper",
587311
+ detail: "Install one of: pkexec (PolKit), zenity, kdialog, or ssh-askpass — then retry.",
587312
+ instance: requestId
587313
+ }));
587314
+ return true;
587315
+ }
587316
+ sendJson(res, 202, {
587317
+ status: "accepted",
587318
+ helper,
587319
+ script: scriptPath2,
587320
+ poll: "/v1/tor/status"
587321
+ });
587322
+ const apiPort = req2.socket?.localPort || parseInt(process.env["OA_API_PORT"] || "11435", 10);
587323
+ runGraphicalSudo2({
587324
+ scriptPath: scriptPath2,
587325
+ env: { OA_API_PORT: String(apiPort) },
587326
+ description: "Open Agents needs admin access to install Tor and configure a hidden service"
587327
+ }).then((r2) => {
587328
+ if (r2.code !== 0) {
587329
+ console.warn(`[tor-enable] sudo helper ${r2.helper} exited ${r2.code}: ${r2.stderr.slice(-300)}`);
587330
+ }
587331
+ }).catch((e2) => {
587332
+ console.warn(`[tor-enable] failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
587333
+ });
587334
+ return true;
587335
+ }
587336
+ async function handleTorDisable(ctx3) {
587337
+ const { req: req2, res, requestId } = ctx3;
587338
+ const reqAuth = req2;
587339
+ if (reqAuth._authScope !== "admin") {
587340
+ sendProblem(res, problemDetails({
587341
+ type: P.forbidden,
587342
+ status: 403,
587343
+ title: "Admin scope required",
587344
+ detail: "Tor teardown requires admin scope.",
587345
+ instance: requestId
587346
+ }));
587347
+ return true;
587348
+ }
587349
+ const scriptPath2 = locateTorScript("destroy_tor.sh");
587350
+ if (!scriptPath2) {
587351
+ sendProblem(res, problemDetails({
587352
+ type: P.internalError,
587353
+ status: 500,
587354
+ title: "destroy_tor.sh not found",
587355
+ detail: "Bundled teardown script missing.",
587356
+ instance: requestId
587357
+ }));
587358
+ return true;
587359
+ }
587360
+ const { runGraphicalSudo: runGraphicalSudo2 } = await Promise.resolve().then(() => (init_graphical_sudo(), graphical_sudo_exports));
587361
+ sendJson(res, 202, { status: "accepted", script: scriptPath2 });
587362
+ 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)}`));
587363
+ return true;
587364
+ }
587110
587365
  async function handleGenerateShare(ctx3) {
587111
587366
  const { req: req2, res, requestId } = ctx3;
587112
587367
  const reqAuth = req2;
@@ -587174,9 +587429,11 @@ async function handleGenerateShare(ctx3) {
587174
587429
  if (onion) plainParams.push(`oa-onion=${encodeURIComponent(onion)}`);
587175
587430
  plainParams.push(`oa-share-label=${encodeURIComponent(label)}`);
587176
587431
  const plainUrl = `${scheme}://${hostPort}/?${plainParams.join("&")}`;
587432
+ const torShareUrl = onion ? `oa-share-tor://${onion}#${fullKey}` : null;
587177
587433
  sendJson(res, 201, {
587178
587434
  shareUrl,
587179
587435
  plainUrl,
587436
+ torShareUrl,
587180
587437
  mode,
587181
587438
  peerId: peerInfo?.peerId || null,
587182
587439
  onion: onion || null,
@@ -587192,7 +587449,7 @@ async function handleGenerateShare(ctx3) {
587192
587449
  tor: !!onion,
587193
587450
  direct: !peerInfo
587194
587451
  },
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."
587452
+ _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
587453
  });
587197
587454
  } catch (err) {
587198
587455
  sendProblem(res, problemDetails({
@@ -587250,13 +587507,13 @@ async function handleRemoteProxy(ctx3) {
587250
587507
  return true;
587251
587508
  }
587252
587509
  const nexusCandidates = [
587253
- join118(process.cwd(), ".oa", "nexus"),
587254
- join118(homedir40(), ".oa", "nexus"),
587255
- join118(homedir40(), ".open-agents", "nexus")
587510
+ join119(process.cwd(), ".oa", "nexus"),
587511
+ join119(homedir40(), ".oa", "nexus"),
587512
+ join119(homedir40(), ".open-agents", "nexus")
587256
587513
  ];
587257
587514
  let nexusDirPath = null;
587258
587515
  for (const p2 of nexusCandidates) {
587259
- if (existsSync102(join118(p2, "status.json"))) {
587516
+ if (existsSync103(join119(p2, "status.json"))) {
587260
587517
  nexusDirPath = p2;
587261
587518
  break;
587262
587519
  }
@@ -587352,7 +587609,7 @@ async function handleRemoteProxy(ctx3) {
587352
587609
  }));
587353
587610
  return true;
587354
587611
  }
587355
- const streamFile = join118(nexusDirPath, `tunnel-${requestId}-${Date.now()}.jsonl`);
587612
+ const streamFile = join119(nexusDirPath, `tunnel-${requestId}-${Date.now()}.jsonl`);
587356
587613
  try {
587357
587614
  const { writeFileSync: _wfs } = await import("node:fs");
587358
587615
  _wfs(streamFile, "");
@@ -587795,14 +588052,14 @@ async function handleListEngines(ctx3) {
587795
588052
  const home = homedir40();
587796
588053
  sendJson(res, 200, {
587797
588054
  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" }
588055
+ { name: "dream", state_file: join119(process.cwd(), ".oa", "dreams"), controllable_via: "SSE + slash commands" },
588056
+ { name: "bless", state_file: join119(process.cwd(), ".oa", "bless-state.json"), controllable_via: "slash commands" },
588057
+ { name: "call", state_file: join119(process.cwd(), ".oa", "call-state.json"), controllable_via: "slash commands" },
588058
+ { name: "listen", state_file: join119(process.cwd(), ".oa", "listen-state.json"), controllable_via: "slash commands" },
588059
+ { name: "telegram", state_file: join119(home, ".open-agents", "telegram-state.json"), controllable_via: "slash commands" },
588060
+ { name: "expose", state_file: join119(process.cwd(), ".oa", "expose-state.json"), controllable_via: "/expose commands" },
588061
+ { name: "nexus", state_file: join119(home, ".open-agents", "nexus-peer-cache.json"), controllable_via: "/nexus commands" },
588062
+ { name: "ipfs", state_file: join119(process.cwd(), ".oa", "ipfs"), controllable_via: "slash commands" }
587806
588063
  ],
587807
588064
  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
588065
  });
@@ -587885,21 +588142,21 @@ async function tryAimsRoute(ctx3) {
587885
588142
  return false;
587886
588143
  }
587887
588144
  function aimsDir() {
587888
- return join118(homedir40(), ".open-agents", "aims");
588145
+ return join119(homedir40(), ".open-agents", "aims");
587889
588146
  }
587890
588147
  function readAimsFile(name10, fallback) {
587891
588148
  try {
587892
- const p2 = join118(aimsDir(), name10);
587893
- if (existsSync102(p2)) return JSON.parse(readFileSync83(p2, "utf-8"));
588149
+ const p2 = join119(aimsDir(), name10);
588150
+ if (existsSync103(p2)) return JSON.parse(readFileSync83(p2, "utf-8"));
587894
588151
  } catch {
587895
588152
  }
587896
588153
  return fallback;
587897
588154
  }
587898
588155
  function writeAimsFile(name10, data) {
587899
588156
  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);
588157
+ const { mkdirSync: mkdirSync68, writeFileSync: wf, renameSync: rn } = __require("node:fs");
588158
+ mkdirSync68(dir, { recursive: true });
588159
+ const finalPath = join119(dir, name10);
587903
588160
  const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
587904
588161
  try {
587905
588162
  wf(tmpPath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
@@ -588229,10 +588486,10 @@ async function handleAimsSuppliers(ctx3) {
588229
588486
  }
588230
588487
  ];
588231
588488
  const sponsorPaths = [
588232
- join118(homedir40(), ".open-agents", "sponsor-cache.json")
588489
+ join119(homedir40(), ".open-agents", "sponsor-cache.json")
588233
588490
  ];
588234
588491
  for (const p2 of sponsorPaths) {
588235
- if (!existsSync102(p2)) continue;
588492
+ if (!existsSync103(p2)) continue;
588236
588493
  try {
588237
588494
  const raw = JSON.parse(readFileSync83(p2, "utf-8"));
588238
588495
  const list = Array.isArray(raw) ? raw : raw?.sponsors ?? [];
@@ -591759,6 +592016,19 @@ function _looksLikePeerId(s) {
591759
592016
  function parseShareInput(raw) {
591760
592017
  const v = String(raw || '').trim();
591761
592018
  if (!v) return null;
592019
+ // oa-share-tor scheme — Tor-only routing via SOCKS5 to <onion>:80
592020
+ if (v.toLowerCase().startsWith('oa-share-tor://')) {
592021
+ const after = v.slice('oa-share-tor://'.length);
592022
+ const hashIdx = after.indexOf('#');
592023
+ if (hashIdx < 0) return null;
592024
+ const onionRaw = after.slice(0, hashIdx);
592025
+ // Strip optional :port suffix; we always dial 80 since hidden services
592026
+ // are configured to forward 80 → local API per the leek_messenger setup.
592027
+ const onion = onionRaw.split(':')[0];
592028
+ const key = after.slice(hashIdx + 1);
592029
+ if (!onion.endsWith('.onion') || !key) return null;
592030
+ return { peerId: null, onion, host: null, key, scheme: 'tor' };
592031
+ }
591762
592032
  // oa-share scheme — custom parser since URL() doesn't always honor it.
591763
592033
  if (v.toLowerCase().startsWith('oa-share://')) {
591764
592034
  const after = v.slice('oa-share://'.length);
@@ -591919,10 +592189,25 @@ async function generateShareUrl() {
591919
592189
  const j = await r.json();
591920
592190
  const safeShare = escapeHtml(j.shareUrl || '');
591921
592191
  const safePlain = escapeHtml(j.plainUrl || '');
592192
+ const safeTor = escapeHtml(j.torShareUrl || '');
592193
+ const torRow = j.torShareUrl
592194
+ ? '<div style="margin:6px 0">' +
592195
+ '<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>' +
592196
+ '<div style="display:flex;gap:6px;align-items:center">' +
592197
+ '<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">' +
592198
+ '<button type="button" onclick="copyShareUrl(\\'tor\\')" style="font-size:0.74rem">copy</button>' +
592199
+ '</div>' +
592200
+ '</div>'
592201
+ : '<div style="margin:8px 0;padding:8px;background:var(--color-bg-input);border:1px dashed var(--color-border);border-radius:var(--radius-sm)">' +
592202
+ '<div style="font-size:0.74rem;margin-bottom:4px">Tor (.onion) is not configured on this OA.</div>' +
592203
+ '<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>' +
592204
+ '<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>' +
592205
+ '<span id="enable-tor-status" style="font-size:0.68rem;margin-left:8px;color:var(--color-fg-muted)"></span>' +
592206
+ '</div>';
591922
592207
  out.innerHTML =
591923
592208
  '<div style="font-weight:500;margin-bottom:6px;color:var(--color-success)">✓ Share URL generated — hand off to remote</div>' +
591924
592209
  '<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>' +
592210
+ '<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
592211
  '<div style="display:flex;gap:6px;align-items:center">' +
591927
592212
  '<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
592213
  '<button type="button" onclick="copyShareUrl(\\'oa-share\\')" style="font-size:0.74rem">copy</button>' +
@@ -591935,17 +592220,22 @@ async function generateShareUrl() {
591935
592220
  '<button type="button" onclick="copyShareUrl(\\'plain\\')" style="font-size:0.74rem">copy</button>' +
591936
592221
  '</div>' +
591937
592222
  '</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>';
592223
+ torRow +
592224
+ '<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
592225
  // Stash for the copy buttons + add to recent.
591940
592226
  window.__oaLastShareUrl = j.shareUrl;
591941
592227
  window.__oaLastPlainUrl = j.plainUrl;
592228
+ window.__oaLastTorUrl = j.torShareUrl || null;
591942
592229
  saveRecentKey({ key: j.key, host: j.host + ':' + j.port, label: j.label || ('shared ' + j.host) });
591943
592230
  } catch (e) {
591944
592231
  out.innerHTML = '<div style="color:var(--color-error)">✗ ' + escapeHtml(e && e.message ? e.message : String(e)) + '</div>';
591945
592232
  }
591946
592233
  }
591947
592234
  function copyShareUrl(which) {
591948
- const v = which === 'plain' ? window.__oaLastPlainUrl : window.__oaLastShareUrl;
592235
+ let v;
592236
+ if (which === 'plain') v = window.__oaLastPlainUrl;
592237
+ else if (which === 'tor') v = window.__oaLastTorUrl;
592238
+ else v = window.__oaLastShareUrl;
591949
592239
  if (!v) return;
591950
592240
  if (navigator.clipboard && navigator.clipboard.writeText) {
591951
592241
  navigator.clipboard.writeText(v).then(
@@ -591965,6 +592255,46 @@ function fallbackCopy(v) {
591965
592255
  window.generateShareUrl = generateShareUrl;
591966
592256
  window.copyShareUrl = copyShareUrl;
591967
592257
 
592258
+ // ─── Enable Tor (graphical sudo) ────────────────────────────────────────
592259
+ async function enableTorShare() {
592260
+ const status = document.getElementById('enable-tor-status');
592261
+ if (status) { status.textContent = 'launching graphical sudo prompt…'; status.style.color = 'var(--color-fg-muted)'; }
592262
+ try {
592263
+ const r = await fetch('/v1/tor/enable', {
592264
+ method: 'POST',
592265
+ headers: { ...headers(), 'Content-Type': 'application/json' },
592266
+ body: '{}',
592267
+ });
592268
+ const j = await r.json().catch(() => ({}));
592269
+ if (r.status === 202) {
592270
+ if (status) {
592271
+ status.textContent = 'started — waiting for hidden service…';
592272
+ status.style.color = 'var(--color-accent)';
592273
+ }
592274
+ // Poll up to 90s for the .onion to appear
592275
+ for (let i = 0; i < 30; i++) {
592276
+ await new Promise(r => setTimeout(r, 3000));
592277
+ const s = await fetch('/v1/tor/status', { headers: headers() }).then(x => x.json()).catch(() => ({}));
592278
+ if (s.onion) {
592279
+ if (status) { status.textContent = '✓ Tor enabled: ' + s.onion; status.style.color = 'var(--color-success)'; }
592280
+ // Re-generate share URL to pick up the .onion field
592281
+ setTimeout(() => generateShareUrl(), 500);
592282
+ return;
592283
+ }
592284
+ }
592285
+ if (status) { status.textContent = '⚠ setup ran but no .onion appeared. Check journalctl -u tor for errors.'; status.style.color = 'var(--color-warning)'; }
592286
+ } else if (r.status === 409) {
592287
+ if (status) { status.textContent = '✓ already enabled — re-generating'; status.style.color = 'var(--color-success)'; }
592288
+ setTimeout(() => generateShareUrl(), 500);
592289
+ } else {
592290
+ if (status) { status.textContent = '✗ ' + (j.detail || ('HTTP ' + r.status)); status.style.color = 'var(--color-error)'; }
592291
+ }
592292
+ } catch (e) {
592293
+ if (status) { status.textContent = '✗ ' + (e && e.message ? e.message : String(e)); status.style.color = 'var(--color-error)'; }
592294
+ }
592295
+ }
592296
+ window.enableTorShare = enableTorShare;
592297
+
591968
592298
  // ─── Remote-state helpers (visual indicator on the key button) ───────
591969
592299
  // When localStorage carries oa.remoteHost we are in REMOTE mode: the
591970
592300
  // key was loaded from an oa-share URL or via on-load ?oa-key=. The key
@@ -596842,14 +597172,14 @@ var init_auth_oidc = __esm({
596842
597172
  });
596843
597173
 
596844
597174
  // 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";
597175
+ import { mkdirSync as mkdirSync61, readFileSync as readFileSync84, writeFileSync as writeFileSync53, existsSync as existsSync104 } from "node:fs";
597176
+ import { join as join120 } from "node:path";
596847
597177
  function initUsageTracker(oaDir) {
596848
- const dir = join119(oaDir, "usage");
596849
- mkdirSync60(dir, { recursive: true });
596850
- usageFile = join119(dir, "token-usage.json");
597178
+ const dir = join120(oaDir, "usage");
597179
+ mkdirSync61(dir, { recursive: true });
597180
+ usageFile = join120(dir, "token-usage.json");
596851
597181
  try {
596852
- if (existsSync103(usageFile)) {
597182
+ if (existsSync104(usageFile)) {
596853
597183
  store = JSON.parse(readFileSync84(usageFile, "utf-8"));
596854
597184
  }
596855
597185
  } catch {
@@ -596886,7 +597216,7 @@ function flush2() {
596886
597216
  if (!initialized2 || !dirty) return;
596887
597217
  try {
596888
597218
  store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
596889
- writeFileSync52(usageFile, JSON.stringify(store, null, 2), "utf-8");
597219
+ writeFileSync53(usageFile, JSON.stringify(store, null, 2), "utf-8");
596890
597220
  dirty = false;
596891
597221
  } catch {
596892
597222
  }
@@ -596914,24 +597244,24 @@ var init_usage_tracker = __esm({
596914
597244
  });
596915
597245
 
596916
597246
  // 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";
597247
+ import { existsSync as existsSync105, readFileSync as readFileSync85, writeFileSync as writeFileSync54, mkdirSync as mkdirSync62, readdirSync as readdirSync35, unlinkSync as unlinkSync23 } from "node:fs";
597248
+ import { join as join121 } from "node:path";
596919
597249
  import { homedir as homedir41 } from "node:os";
596920
597250
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes22, scryptSync as scryptSync3 } from "node:crypto";
596921
597251
  function globalProfileDir() {
596922
- return join120(homedir41(), ".open-agents", "profiles");
597252
+ return join121(homedir41(), ".open-agents", "profiles");
596923
597253
  }
596924
597254
  function projectProfileDir(projectDir2) {
596925
- return join120(projectDir2 || process.cwd(), ".oa", "profiles");
597255
+ return join121(projectDir2 || process.cwd(), ".oa", "profiles");
596926
597256
  }
596927
597257
  function listProfiles(projectDir2) {
596928
597258
  const result = [];
596929
597259
  const seen = /* @__PURE__ */ new Set();
596930
597260
  const projDir = projectProfileDir(projectDir2);
596931
- if (existsSync104(projDir)) {
597261
+ if (existsSync105(projDir)) {
596932
597262
  for (const f2 of readdirSync35(projDir).filter((f3) => f3.endsWith(".json"))) {
596933
597263
  try {
596934
- const raw = JSON.parse(readFileSync85(join120(projDir, f2), "utf8"));
597264
+ const raw = JSON.parse(readFileSync85(join121(projDir, f2), "utf8"));
596935
597265
  const name10 = f2.replace(".json", "");
596936
597266
  seen.add(name10);
596937
597267
  result.push({
@@ -596945,12 +597275,12 @@ function listProfiles(projectDir2) {
596945
597275
  }
596946
597276
  }
596947
597277
  const globDir = globalProfileDir();
596948
- if (existsSync104(globDir)) {
597278
+ if (existsSync105(globDir)) {
596949
597279
  for (const f2 of readdirSync35(globDir).filter((f3) => f3.endsWith(".json"))) {
596950
597280
  const name10 = f2.replace(".json", "");
596951
597281
  if (seen.has(name10)) continue;
596952
597282
  try {
596953
- const raw = JSON.parse(readFileSync85(join120(globDir, f2), "utf8"));
597283
+ const raw = JSON.parse(readFileSync85(join121(globDir, f2), "utf8"));
596954
597284
  result.push({
596955
597285
  name: name10,
596956
597286
  description: raw.description || "",
@@ -596965,9 +597295,9 @@ function listProfiles(projectDir2) {
596965
597295
  }
596966
597296
  function loadProfile(name10, password, projectDir2) {
596967
597297
  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;
597298
+ const projPath = join121(projectProfileDir(projectDir2), `${sanitized}.json`);
597299
+ const globPath = join121(globalProfileDir(), `${sanitized}.json`);
597300
+ const filePath = existsSync105(projPath) ? projPath : existsSync105(globPath) ? globPath : null;
596971
597301
  if (!filePath) return null;
596972
597302
  const raw = JSON.parse(readFileSync85(filePath, "utf8"));
596973
597303
  if (raw.encrypted === true) {
@@ -596978,23 +597308,23 @@ function loadProfile(name10, password, projectDir2) {
596978
597308
  }
596979
597309
  function saveProfile(profile, password, scope = "global", projectDir2) {
596980
597310
  const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
596981
- mkdirSync61(dir, { recursive: true });
597311
+ mkdirSync62(dir, { recursive: true });
596982
597312
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
596983
- const filePath = join120(dir, `${sanitized}.json`);
597313
+ const filePath = join121(dir, `${sanitized}.json`);
596984
597314
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
596985
597315
  if (password) {
596986
597316
  const encrypted = encryptProfile(profile, password);
596987
- writeFileSync53(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
597317
+ writeFileSync54(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
596988
597318
  } else {
596989
597319
  profile.encrypted = false;
596990
- writeFileSync53(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
597320
+ writeFileSync54(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
596991
597321
  }
596992
597322
  }
596993
597323
  function deleteProfile(name10, scope = "global", projectDir2) {
596994
597324
  const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
596995
597325
  const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
596996
- const filePath = join120(dir, `${sanitized}.json`);
596997
- if (existsSync104(filePath)) {
597326
+ const filePath = join121(dir, `${sanitized}.json`);
597327
+ if (existsSync105(filePath)) {
596998
597328
  unlinkSync23(filePath);
596999
597329
  return true;
597000
597330
  }
@@ -597108,24 +597438,24 @@ var init_profiles = __esm({
597108
597438
  });
597109
597439
 
597110
597440
  // 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";
597441
+ import { execSync as execSync56, spawn as spawn25 } from "node:child_process";
597442
+ import { existsSync as existsSync106, mkdirSync as mkdirSync63, writeFileSync as writeFileSync55 } from "node:fs";
597443
+ import { join as join122, resolve as resolve37, dirname as dirname35 } from "node:path";
597114
597444
  import { homedir as homedir42 } from "node:os";
597115
597445
  import { fileURLToPath as fileURLToPath16 } from "node:url";
597116
597446
  function getDockerDir() {
597117
597447
  try {
597118
597448
  if (typeof __dirname !== "undefined") {
597119
- return join121(__dirname, "..", "..", "..", "docker");
597449
+ return join122(__dirname, "..", "..", "..", "docker");
597120
597450
  }
597121
597451
  } catch {
597122
597452
  }
597123
597453
  try {
597124
597454
  const thisDir = dirname35(fileURLToPath16(import.meta.url));
597125
- return join121(thisDir, "..", "..", "..", "docker");
597455
+ return join122(thisDir, "..", "..", "..", "docker");
597126
597456
  } catch {
597127
597457
  }
597128
- return join121(process.cwd(), "docker");
597458
+ return join122(process.cwd(), "docker");
597129
597459
  }
597130
597460
  function isDockerAvailable() {
597131
597461
  try {
@@ -597256,11 +597586,11 @@ async function ensureOaImage(force = false) {
597256
597586
  }
597257
597587
  let buildContext;
597258
597588
  const dockerDir = getDockerDir();
597259
- if (existsSync105(join121(dockerDir, "Dockerfile"))) {
597589
+ if (existsSync106(join122(dockerDir, "Dockerfile"))) {
597260
597590
  buildContext = dockerDir;
597261
597591
  } else {
597262
- buildContext = join121(homedir42(), ".oa", "docker-build");
597263
- mkdirSync62(buildContext, { recursive: true });
597592
+ buildContext = join122(homedir42(), ".oa", "docker-build");
597593
+ mkdirSync63(buildContext, { recursive: true });
597264
597594
  writeDockerfiles(buildContext);
597265
597595
  }
597266
597596
  try {
@@ -597334,8 +597664,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
597334
597664
  if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
597335
597665
  exec "$@"
597336
597666
  `;
597337
- writeFileSync54(join121(dir, "Dockerfile"), dockerfile);
597338
- writeFileSync54(join121(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
597667
+ writeFileSync55(join122(dir, "Dockerfile"), dockerfile);
597668
+ writeFileSync55(join122(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
597339
597669
  }
597340
597670
  function hasNvidiaGpu() {
597341
597671
  try {
@@ -597389,7 +597719,7 @@ function runInContainer(opts) {
597389
597719
  if (opts.maxTurns) oaArgs.push("--max-turns", String(opts.maxTurns));
597390
597720
  if (opts.timeoutS) oaArgs.push("--timeout", String(opts.timeoutS));
597391
597721
  args.push(...oaArgs);
597392
- return spawn24("docker", args, {
597722
+ return spawn25("docker", args, {
597393
597723
  stdio: ["ignore", "pipe", "pipe"]
597394
597724
  });
597395
597725
  }
@@ -597588,23 +597918,23 @@ import * as http5 from "node:http";
597588
597918
  import * as https3 from "node:https";
597589
597919
  import { createRequire as createRequire5 } from "node:module";
597590
597920
  import { fileURLToPath as fileURLToPath17 } from "node:url";
597591
- import { dirname as dirname36, join as join122, resolve as resolve38 } from "node:path";
597921
+ import { dirname as dirname36, join as join123, resolve as resolve38 } from "node:path";
597592
597922
  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";
597923
+ import { spawn as spawn26, execSync as execSync57 } from "node:child_process";
597924
+ 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
597925
  import { randomBytes as randomBytes23, randomUUID as randomUUID16 } from "node:crypto";
597596
597926
  import { createHash as createHash19 } from "node:crypto";
597597
597927
  function getVersion3() {
597598
597928
  try {
597599
597929
  const thisDir = dirname36(fileURLToPath17(import.meta.url));
597600
597930
  const candidates = [
597601
- join122(thisDir, "..", "package.json"),
597602
- join122(thisDir, "..", "..", "package.json"),
597603
- join122(thisDir, "..", "..", "..", "package.json")
597931
+ join123(thisDir, "..", "package.json"),
597932
+ join123(thisDir, "..", "..", "package.json"),
597933
+ join123(thisDir, "..", "..", "..", "package.json")
597604
597934
  ];
597605
597935
  for (const pkgPath of candidates) {
597606
597936
  try {
597607
- if (!existsSync106(pkgPath)) continue;
597937
+ if (!existsSync107(pkgPath)) continue;
597608
597938
  const pkg = require3(pkgPath);
597609
597939
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
597610
597940
  return pkg.version ?? "0.0.0";
@@ -597806,8 +598136,8 @@ function isOriginAllowed(origin) {
597806
598136
  if (!origin) return true;
597807
598137
  let accessMode = (process.env["OA_ACCESS"] || "").toLowerCase().trim();
597808
598138
  try {
597809
- const accessFile = join122(homedir43(), ".open-agents", "access");
597810
- if (existsSync106(accessFile)) {
598139
+ const accessFile = join123(homedir43(), ".open-agents", "access");
598140
+ if (existsSync107(accessFile)) {
597811
598141
  const persisted = readFileSync86(accessFile, "utf8").trim().toLowerCase();
597812
598142
  if (persisted === "any" || persisted === "lan" || persisted === "loopback") {
597813
598143
  accessMode = persisted;
@@ -597868,7 +598198,7 @@ async function retrieveMemoryContext(userMessage, sessionId, maxEpisodes = 5) {
597868
598198
  if (!memMod || !memMod.EpisodeStore) {
597869
598199
  return { contextBlock: "", retrieved: [] };
597870
598200
  }
597871
- const dbPath = join122(homedir43(), ".open-agents", "memory.db");
598201
+ const dbPath = join123(homedir43(), ".open-agents", "memory.db");
597872
598202
  const store2 = new memMod.EpisodeStore(dbPath);
597873
598203
  const recent = store2.search({ limit: 30, sessionId: void 0 }) ?? [];
597874
598204
  const qLower = userMessage.toLowerCase();
@@ -597911,7 +598241,7 @@ async function writeMemoryEpisodes(sessionId, userMessage, assistantContent, too
597911
598241
  try {
597912
598242
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2)).catch(() => null);
597913
598243
  if (!memMod || !memMod.EpisodeStore) return 0;
597914
- const dbPath = join122(homedir43(), ".open-agents", "memory.db");
598244
+ const dbPath = join123(homedir43(), ".open-agents", "memory.db");
597915
598245
  const store2 = new memMod.EpisodeStore(dbPath);
597916
598246
  let written = 0;
597917
598247
  try {
@@ -598233,13 +598563,13 @@ function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError, ti
598233
598563
  }
598234
598564
  function jobsDir() {
598235
598565
  const root = resolve38(process.cwd());
598236
- const dir = join122(root, ".oa", "jobs");
598237
- mkdirSync63(dir, { recursive: true });
598566
+ const dir = join123(root, ".oa", "jobs");
598567
+ mkdirSync64(dir, { recursive: true });
598238
598568
  return dir;
598239
598569
  }
598240
598570
  function loadJob(id) {
598241
- const file = join122(jobsDir(), `${id}.json`);
598242
- if (!existsSync106(file)) return null;
598571
+ const file = join123(jobsDir(), `${id}.json`);
598572
+ if (!existsSync107(file)) return null;
598243
598573
  try {
598244
598574
  return JSON.parse(readFileSync86(file, "utf-8"));
598245
598575
  } catch {
@@ -598248,12 +598578,12 @@ function loadJob(id) {
598248
598578
  }
598249
598579
  function listJobs() {
598250
598580
  const dir = jobsDir();
598251
- if (!existsSync106(dir)) return [];
598581
+ if (!existsSync107(dir)) return [];
598252
598582
  const files = readdirSync36(dir).filter((f2) => f2.endsWith(".json")).sort();
598253
598583
  const jobs = [];
598254
598584
  for (const file of files) {
598255
598585
  try {
598256
- jobs.push(JSON.parse(readFileSync86(join122(dir, file), "utf-8")));
598586
+ jobs.push(JSON.parse(readFileSync86(join123(dir, file), "utf-8")));
598257
598587
  } catch {
598258
598588
  }
598259
598589
  }
@@ -598263,12 +598593,12 @@ function pruneOldJobs() {
598263
598593
  const retentionH = parseFloat(process.env["OA_RUN_RETENTION_H"] || "24");
598264
598594
  const cutoffMs = Date.now() - (Number.isFinite(retentionH) && retentionH > 0 ? retentionH : 24) * 36e5;
598265
598595
  const dir = jobsDir();
598266
- if (!existsSync106(dir)) return { pruned: 0, kept: 0 };
598596
+ if (!existsSync107(dir)) return { pruned: 0, kept: 0 };
598267
598597
  let pruned = 0;
598268
598598
  let kept = 0;
598269
598599
  for (const file of readdirSync36(dir)) {
598270
598600
  if (!file.endsWith(".json")) continue;
598271
- const path8 = join122(dir, file);
598601
+ const path8 = join123(dir, file);
598272
598602
  try {
598273
598603
  const job = JSON.parse(readFileSync86(path8, "utf-8"));
598274
598604
  if (job.status === "running") {
@@ -598283,7 +598613,7 @@ function pruneOldJobs() {
598283
598613
  } catch {
598284
598614
  }
598285
598615
  const outFile = path8.replace(/\.json$/, ".output");
598286
- if (existsSync106(outFile)) {
598616
+ if (existsSync107(outFile)) {
598287
598617
  try {
598288
598618
  unlinkSync24(outFile);
598289
598619
  } catch {
@@ -598576,14 +598906,14 @@ function autoSeedTodosFromPrompt(prompt) {
598576
598906
  return [];
598577
598907
  }
598578
598908
  function atomicJobWrite(dir, id, job) {
598579
- const finalPath = join122(dir, `${id}.json`);
598909
+ const finalPath = join123(dir, `${id}.json`);
598580
598910
  const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
598581
598911
  try {
598582
- writeFileSync55(tmpPath, JSON.stringify(job, null, 2), "utf-8");
598912
+ writeFileSync56(tmpPath, JSON.stringify(job, null, 2), "utf-8");
598583
598913
  renameSync8(tmpPath, finalPath);
598584
598914
  } catch {
598585
598915
  try {
598586
- writeFileSync55(finalPath, JSON.stringify(job, null, 2), "utf-8");
598916
+ writeFileSync56(finalPath, JSON.stringify(job, null, 2), "utf-8");
598587
598917
  } catch {
598588
598918
  }
598589
598919
  try {
@@ -599785,7 +600115,7 @@ ${task}` : task;
599785
600115
  runEnv["OA_RUN_SCOPE"] = req2._authScope || "admin";
599786
600116
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
599787
600117
  if (currentCfg.apiKey) runEnv["OA_API_KEY_INHERIT"] = currentCfg.apiKey;
599788
- const child = spawn25(process.execPath, [oaBin, ...args], {
600118
+ const child = spawn26(process.execPath, [oaBin, ...args], {
599789
600119
  cwd: resolve38(process.cwd()),
599790
600120
  env: runEnv,
599791
600121
  stdio: ["ignore", "pipe", "pipe"]
@@ -600002,15 +600332,15 @@ ${task}` : task;
600002
600332
  });
600003
600333
  }
600004
600334
  function updateStateFile() {
600005
- return join122(homedir43(), ".open-agents", "update-state.json");
600335
+ return join123(homedir43(), ".open-agents", "update-state.json");
600006
600336
  }
600007
600337
  function updateLogPath() {
600008
- return join122(homedir43(), ".open-agents", "update.log");
600338
+ return join123(homedir43(), ".open-agents", "update.log");
600009
600339
  }
600010
600340
  function readUpdateState() {
600011
600341
  try {
600012
600342
  const p2 = updateStateFile();
600013
- if (!existsSync106(p2)) return null;
600343
+ if (!existsSync107(p2)) return null;
600014
600344
  return JSON.parse(readFileSync86(p2, "utf-8"));
600015
600345
  } catch {
600016
600346
  return null;
@@ -600018,11 +600348,11 @@ function readUpdateState() {
600018
600348
  }
600019
600349
  function writeUpdateState(state) {
600020
600350
  try {
600021
- const dir = join122(homedir43(), ".open-agents");
600022
- mkdirSync63(dir, { recursive: true });
600351
+ const dir = join123(homedir43(), ".open-agents");
600352
+ mkdirSync64(dir, { recursive: true });
600023
600353
  const finalPath = updateStateFile();
600024
600354
  const tmpPath = `${finalPath}.tmp.${process.pid}`;
600025
- writeFileSync55(tmpPath, JSON.stringify(state, null, 2), "utf-8");
600355
+ writeFileSync56(tmpPath, JSON.stringify(state, null, 2), "utf-8");
600026
600356
  renameSync8(tmpPath, finalPath);
600027
600357
  } catch {
600028
600358
  }
@@ -600066,15 +600396,15 @@ async function handleV1Update(req2, res, requestId) {
600066
600396
  const { execSync: es } = require3("node:child_process");
600067
600397
  const isWin2 = process.platform === "win32";
600068
600398
  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)) {
600399
+ for (const candidate of isWin2 ? [join123(nodeDir, "npm.cmd"), join123(nodeDir, "npm")] : [join123(nodeDir, "npm"), "/usr/local/bin/npm", "/usr/bin/npm"]) {
600400
+ if (existsSync107(candidate)) {
600071
600401
  npmBin = candidate;
600072
600402
  break;
600073
600403
  }
600074
600404
  }
600075
600405
  if (!npmBin) npmBin = isWin2 ? "npm.cmd" : "npm";
600076
600406
  const pkgSpec = `open-agents-ai@${targetVersion}`;
600077
- const dir = join122(homedir43(), ".open-agents");
600407
+ const dir = join123(homedir43(), ".open-agents");
600078
600408
  fs7.mkdirSync(dir, { recursive: true });
600079
600409
  const logFd = fs7.openSync(logPath3, "w");
600080
600410
  const npmPrefix = dirname36(nodeDir);
@@ -600084,13 +600414,13 @@ async function handleV1Update(req2, res, requestId) {
600084
600414
  globalBinDir = es(`${npmBin} bin -g`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
600085
600415
  } else {
600086
600416
  const npmCliCandidates = [
600087
- join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600088
- join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600417
+ join123(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600418
+ join123(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600089
600419
  ];
600090
600420
  let npmCli = "";
600091
600421
  for (const c9 of npmCliCandidates) {
600092
600422
  try {
600093
- if (existsSync106(c9)) {
600423
+ if (existsSync107(c9)) {
600094
600424
  npmCli = c9;
600095
600425
  break;
600096
600426
  }
@@ -600114,7 +600444,7 @@ async function handleV1Update(req2, res, requestId) {
600114
600444
  cleanEnv.PATH = pathParts.join(":");
600115
600445
  let child;
600116
600446
  if (isWin2) {
600117
- child = spawn25(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600447
+ child = spawn26(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600118
600448
  detached: true,
600119
600449
  stdio: ["ignore", logFd, logFd],
600120
600450
  windowsHide: true,
@@ -600122,13 +600452,13 @@ async function handleV1Update(req2, res, requestId) {
600122
600452
  });
600123
600453
  } else {
600124
600454
  const npmCliCandidates = [
600125
- join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600126
- join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600455
+ join123(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
600456
+ join123(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
600127
600457
  ];
600128
600458
  let npmCli = "";
600129
600459
  for (const c9 of npmCliCandidates) {
600130
600460
  try {
600131
- if (existsSync106(c9)) {
600461
+ if (existsSync107(c9)) {
600132
600462
  npmCli = c9;
600133
600463
  break;
600134
600464
  }
@@ -600136,13 +600466,13 @@ async function handleV1Update(req2, res, requestId) {
600136
600466
  }
600137
600467
  }
600138
600468
  if (npmCli) {
600139
- child = spawn25(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600469
+ child = spawn26(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600140
600470
  detached: true,
600141
600471
  stdio: ["ignore", logFd, logFd],
600142
600472
  env: cleanEnv
600143
600473
  });
600144
600474
  } else {
600145
- child = spawn25(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600475
+ child = spawn26(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
600146
600476
  detached: true,
600147
600477
  stdio: ["ignore", logFd, logFd],
600148
600478
  env: cleanEnv
@@ -600153,7 +600483,7 @@ async function handleV1Update(req2, res, requestId) {
600153
600483
  const installPid = child.pid ?? 0;
600154
600484
  if (installPid > 0 && !isWin2) {
600155
600485
  try {
600156
- const follower = spawn25("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
600486
+ const follower = spawn26("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
600157
600487
  detached: true,
600158
600488
  stdio: "ignore"
600159
600489
  });
@@ -600166,8 +600496,8 @@ async function handleV1Update(req2, res, requestId) {
600166
600496
  }
600167
600497
  let oaAbs = "oa";
600168
600498
  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;
600499
+ const which2 = es("command -v oa 2>/dev/null || which oa 2>/dev/null", { encoding: "utf8", timeout: 2e3, stdio: "pipe", env: cleanEnv }).trim();
600500
+ if (which2) oaAbs = which2;
600171
600501
  } catch {
600172
600502
  }
600173
600503
  const relaunchScript = [
@@ -600176,7 +600506,7 @@ async function handleV1Update(req2, res, requestId) {
600176
600506
  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
600507
  `kill -TERM ${process.pid} >/dev/null 2>&1 || true`
600178
600508
  ].join("; ");
600179
- const relauncher = spawn25("bash", ["-c", relaunchScript], {
600509
+ const relauncher = spawn26("bash", ["-c", relaunchScript], {
600180
600510
  detached: true,
600181
600511
  stdio: "ignore",
600182
600512
  env: cleanEnv
@@ -600225,7 +600555,7 @@ function handleV1UpdateStatus(res) {
600225
600555
  let logTail = "";
600226
600556
  let exitCode = null;
600227
600557
  try {
600228
- if (existsSync106(logPath3)) {
600558
+ if (existsSync107(logPath3)) {
600229
600559
  const raw = readFileSync86(logPath3, "utf-8");
600230
600560
  const m2 = raw.match(/__EXIT_CODE=(\d+)/);
600231
600561
  if (m2) exitCode = parseInt(m2[1], 10);
@@ -600322,8 +600652,8 @@ async function handleV1Run(req2, res) {
600322
600652
  if (workingDir) {
600323
600653
  cwd4 = resolve38(workingDir);
600324
600654
  } else if (isolate) {
600325
- const wsDir = join122(dir, "..", "workspaces", id);
600326
- mkdirSync63(wsDir, { recursive: true });
600655
+ const wsDir = join123(dir, "..", "workspaces", id);
600656
+ mkdirSync64(wsDir, { recursive: true });
600327
600657
  cwd4 = wsDir;
600328
600658
  } else {
600329
600659
  cwd4 = resolve38(process.cwd());
@@ -600398,7 +600728,7 @@ async function handleV1Run(req2, res) {
600398
600728
  });
600399
600729
  job.sandbox = "container";
600400
600730
  } else {
600401
- child = spawn25(process.execPath, [oaBin, ...args], {
600731
+ child = spawn26(process.execPath, [oaBin, ...args], {
600402
600732
  cwd: cwd4,
600403
600733
  env: runEnv,
600404
600734
  stdio: ["ignore", "pipe", "pipe"],
@@ -600509,7 +600839,7 @@ async function handleV1Run(req2, res) {
600509
600839
  let output = "";
600510
600840
  let tailBytes = 0;
600511
600841
  const TAIL_BUDGET = 1048576;
600512
- const outputWriter = new DiskTaskOutput(join122(dir, `${id}.output`));
600842
+ const outputWriter = new DiskTaskOutput(join123(dir, `${id}.output`));
600513
600843
  job.outputFile = outputWriter.path;
600514
600844
  atomicJobWrite(dir, id, job);
600515
600845
  child.stdout?.on("data", (chunk) => {
@@ -600908,7 +601238,7 @@ async function handlePostCommand(res, cmd) {
600908
601238
  return;
600909
601239
  }
600910
601240
  try {
600911
- const child = spawn25("node", [oaBin, "run", `/${cmd}`, "--json"], {
601241
+ const child = spawn26("node", [oaBin, "run", `/${cmd}`, "--json"], {
600912
601242
  env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
600913
601243
  stdio: ["ignore", "pipe", "pipe"],
600914
601244
  timeout: 3e4
@@ -601425,11 +601755,11 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
601425
601755
  jsonResponse(res, 400, { error: "audio_too_small", message: "Reference audio must be at least ~4 KB" });
601426
601756
  return;
601427
601757
  }
601428
- const { tmpdir: tmpdir22 } = await import("node:os");
601429
- const { writeFileSync: writeFileSync59, unlinkSync: unlinkSync25 } = await import("node:fs");
601758
+ const { tmpdir: tmpdir23 } = await import("node:os");
601759
+ const { writeFileSync: writeFileSync60, unlinkSync: unlinkSync25 } = await import("node:fs");
601430
601760
  const { join: pjoin } = await import("node:path");
601431
- const tmpPath = pjoin(tmpdir22(), `oa-clone-upload-${Date.now()}-${safeName}`);
601432
- writeFileSync59(tmpPath, buf);
601761
+ const tmpPath = pjoin(tmpdir23(), `oa-clone-upload-${Date.now()}-${safeName}`);
601762
+ writeFileSync60(tmpPath, buf);
601433
601763
  try {
601434
601764
  const ve = getVoiceEngine();
601435
601765
  const msg = await ve.setCloneVoice(tmpPath);
@@ -601979,7 +602309,7 @@ data: ${JSON.stringify(data)}
601979
602309
  }
601980
602310
  for (const f2 of seenFiles) {
601981
602311
  try {
601982
- writeFileSync55(f2, JSON.stringify({ tasks: [] }, null, 2));
602312
+ writeFileSync56(f2, JSON.stringify({ tasks: [] }, null, 2));
601983
602313
  deleted++;
601984
602314
  } catch {
601985
602315
  }
@@ -602280,7 +602610,7 @@ ${historyLines}
602280
602610
  }
602281
602611
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
602282
602612
  if (currentCfg.apiKey) runEnv["OA_API_KEY_INHERIT"] = currentCfg.apiKey;
602283
- const child = spawn25(process.execPath, [oaBin, ...args], {
602613
+ const child = spawn26(process.execPath, [oaBin, ...args], {
602284
602614
  cwd: cwdPath,
602285
602615
  env: runEnv,
602286
602616
  stdio: ["ignore", "pipe", "pipe"],
@@ -603083,7 +603413,7 @@ ${steering}`;
603083
603413
  function getScheduleRoots() {
603084
603414
  const rootsEnv = process.env["OA_SCHEDULE_ROOTS"] || "";
603085
603415
  const roots = rootsEnv.split(rootsEnv.includes(";") ? ";" : ":").filter(Boolean);
603086
- const defaults3 = [process.cwd(), join122(homedir43(), "Documents")];
603416
+ const defaults3 = [process.cwd(), join123(homedir43(), "Documents")];
603087
603417
  const set = /* @__PURE__ */ new Set([...defaults3, ...roots]);
603088
603418
  return [...set];
603089
603419
  }
@@ -603095,8 +603425,8 @@ function listScheduledTasks() {
603095
603425
  for (const root of roots) {
603096
603426
  try {
603097
603427
  walk(root, 0, (dir) => {
603098
- if (dir.endsWith(`${join122(".oa", "scheduled")}`) || dir.includes(`${join122(".oa", "scheduled")}`)) {
603099
- const file = join122(dir, "tasks.json");
603428
+ if (dir.endsWith(`${join123(".oa", "scheduled")}`) || dir.includes(`${join123(".oa", "scheduled")}`)) {
603429
+ const file = join123(dir, "tasks.json");
603100
603430
  try {
603101
603431
  const raw = readFileSync86(file, "utf-8");
603102
603432
  const json = JSON.parse(raw);
@@ -603163,7 +603493,7 @@ function walk(dir, depth, onDir, maxDepth) {
603163
603493
  if (e2.name === "node_modules" || e2.name.startsWith(".")) {
603164
603494
  if (e2.name !== ".oa") continue;
603165
603495
  }
603166
- const child = join122(dir, e2.name);
603496
+ const child = join123(dir, e2.name);
603167
603497
  walk(child, depth + 1, onDir, maxDepth);
603168
603498
  }
603169
603499
  }
@@ -603179,11 +603509,11 @@ function setScheduledEnabled(id, enabled2) {
603179
603509
  arr[target.index].enabled = enabled2;
603180
603510
  if (Array.isArray(json?.tasks)) {
603181
603511
  json.tasks = arr;
603182
- writeFileSync55(target.file, JSON.stringify(json, null, 2));
603512
+ writeFileSync56(target.file, JSON.stringify(json, null, 2));
603183
603513
  } else if (Array.isArray(json)) {
603184
- writeFileSync55(target.file, JSON.stringify(arr, null, 2));
603514
+ writeFileSync56(target.file, JSON.stringify(arr, null, 2));
603185
603515
  } else {
603186
- writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
603516
+ writeFileSync56(target.file, JSON.stringify({ tasks: arr }, null, 2));
603187
603517
  }
603188
603518
  if (!enabled2) {
603189
603519
  try {
@@ -603213,11 +603543,11 @@ function deleteScheduledById(id) {
603213
603543
  arr.splice(target.index, 1);
603214
603544
  if (Array.isArray(json?.tasks)) {
603215
603545
  json.tasks = arr;
603216
- writeFileSync55(target.file, JSON.stringify(json, null, 2));
603546
+ writeFileSync56(target.file, JSON.stringify(json, null, 2));
603217
603547
  } else if (Array.isArray(json)) {
603218
- writeFileSync55(target.file, JSON.stringify(arr, null, 2));
603548
+ writeFileSync56(target.file, JSON.stringify(arr, null, 2));
603219
603549
  } else {
603220
- writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
603550
+ writeFileSync56(target.file, JSON.stringify({ tasks: arr }, null, 2));
603221
603551
  }
603222
603552
  const candidates = [];
603223
603553
  if (id) candidates.push(id);
@@ -603470,7 +603800,7 @@ function reconcileScheduledTasks(apply) {
603470
603800
  const errors = [];
603471
603801
  for (const f2 of found) {
603472
603802
  const wdir = f2.workingDir || process.cwd();
603473
- const file = join122(wdir, ".oa", "scheduled", "tasks.json");
603803
+ const file = join123(wdir, ".oa", "scheduled", "tasks.json");
603474
603804
  try {
603475
603805
  let json = { tasks: [] };
603476
603806
  try {
@@ -603485,9 +603815,9 @@ function reconcileScheduledTasks(apply) {
603485
603815
  const entry = { task: f2.task || `legacy ${f2.id}`, schedule: f2.cron, enabled: true };
603486
603816
  arr.push(entry);
603487
603817
  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));
603818
+ mkdirSync64(join123(wdir, ".oa", "scheduled"), { recursive: true });
603819
+ mkdirSync64(join123(wdir, ".oa", "scheduled", "logs"), { recursive: true });
603820
+ writeFileSync56(file, JSON.stringify(toWrite, null, 2));
603491
603821
  adopted.push({ file, index: arr.length - 1 });
603492
603822
  }
603493
603823
  } else {
@@ -603531,32 +603861,32 @@ function writeCrontabLines(lines) {
603531
603861
  }
603532
603862
  function canonicalCronLine(rec) {
603533
603863
  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");
603864
+ const logDir = join123(rec.workingDir, ".oa", "scheduled", "logs");
603865
+ const logFile = join123(logDir, `${rec.id}.log`);
603866
+ const storeFile = join123(rec.workingDir, ".oa", "scheduled", "tasks.json");
603537
603867
  const taskEsc = rec.task.replace(/'/g, "'\\''");
603538
- const lockDir = join122(rec.workingDir, ".oa", "run");
603539
- const lockPath = join122(lockDir, `${rec.id}.lock`);
603868
+ const lockDir = join123(rec.workingDir, ".oa", "run");
603869
+ const lockPath = join123(lockDir, `${rec.id}.lock`);
603540
603870
  const wrapper = [
603541
603871
  `cd ${JSON.stringify(rec.workingDir)}`,
603542
603872
  `mkdir -p ${JSON.stringify(logDir)}`,
603543
603873
  `mkdir -p ${JSON.stringify(lockDir)}`,
603544
603874
  `if mkdir ${JSON.stringify(lockPath)} 2>/dev/null; then`,
603545
- ` echo $$ > ${JSON.stringify(join122(lockPath, "pid"))}`,
603875
+ ` echo $$ > ${JSON.stringify(join123(lockPath, "pid"))}`,
603546
603876
  ` trap 'rm -rf ${lockPath}' EXIT`,
603547
603877
  `else`,
603548
- ` if [ -f ${JSON.stringify(join122(lockPath, "pid"))} ]; then`,
603549
- ` oldpid=$(cat ${JSON.stringify(join122(lockPath, "pid"))} 2>/dev/null || echo)`,
603878
+ ` if [ -f ${JSON.stringify(join123(lockPath, "pid"))} ]; then`,
603879
+ ` oldpid=$(cat ${JSON.stringify(join123(lockPath, "pid"))} 2>/dev/null || echo)`,
603550
603880
  ` if [ -n "$oldpid" ] && kill -0 "$oldpid" 2>/dev/null; then`,
603551
603881
  ` echo "[oa-scheduler] ${rec.id} already running as PID $oldpid; skipping" >> ${JSON.stringify(logFile)}`,
603552
603882
  ` exit 0`,
603553
603883
  ` else`,
603554
603884
  ` 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`,
603885
+ ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join123(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603556
603886
  ` fi`,
603557
603887
  ` else`,
603558
603888
  ` 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`,
603889
+ ` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join123(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
603560
603890
  ` fi`,
603561
603891
  `fi`,
603562
603892
  `${oaBin} '${taskEsc}' >> ${JSON.stringify(logFile)} 2>&1; _oa_exit=$?`,
@@ -603588,9 +603918,9 @@ function fixupOrMigrateScheduled(mode, dryRun) {
603588
603918
  try {
603589
603919
  if (!f2.workingDir || !f2.task) continue;
603590
603920
  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`);
603921
+ const unitDir = join123(homedir43(), ".config", "systemd", "user");
603922
+ const svc = join123(unitDir, `${unitBase}.service`);
603923
+ const tim = join123(unitDir, `${unitBase}.timer`);
603594
603924
  const oaBin = findOaBinary4();
603595
603925
  const rec = { id: f2.id, cron: f2.cron, workingDir: f2.workingDir, task: f2.task };
603596
603926
  const cmd = canonicalCronLine(rec).split(" ").slice(5).join(" ");
@@ -603620,9 +603950,9 @@ Persistent=true
603620
603950
  WantedBy=timers.target
603621
603951
  `;
603622
603952
  if (!dryRun) {
603623
- mkdirSync63(unitDir, { recursive: true });
603624
- writeFileSync55(svc, svcText);
603625
- writeFileSync55(tim, timText);
603953
+ mkdirSync64(unitDir, { recursive: true });
603954
+ writeFileSync56(svc, svcText);
603955
+ writeFileSync56(tim, timText);
603626
603956
  try {
603627
603957
  const { execSync: es } = require3("node:child_process");
603628
603958
  es("systemctl --user daemon-reload", { stdio: "pipe" });
@@ -603716,8 +604046,8 @@ function startApiServer(options2 = {}) {
603716
604046
  const config = loadConfig();
603717
604047
  const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
603718
604048
  const cwd4 = process.cwd();
603719
- initAuditLog(join122(cwd4, ".oa"));
603720
- initUsageTracker(join122(cwd4, ".oa"));
604049
+ initAuditLog(join123(cwd4, ".oa"));
604050
+ initUsageTracker(join123(cwd4, ".oa"));
603721
604051
  try {
603722
604052
  const taskMgr = getSharedTaskManager();
603723
604053
  taskMgr.setEventPublisher((type, data, opts) => {
@@ -603759,7 +604089,7 @@ function startApiServer(options2 = {}) {
603759
604089
  try {
603760
604090
  const dir = todoDir();
603761
604091
  try {
603762
- mkdirSync63(dir, { recursive: true });
604092
+ mkdirSync64(dir, { recursive: true });
603763
604093
  } catch {
603764
604094
  }
603765
604095
  const cache8 = /* @__PURE__ */ new Map();
@@ -603768,7 +604098,7 @@ function startApiServer(options2 = {}) {
603768
604098
  if (!f2.endsWith(".json") || f2.includes(".tmp.")) continue;
603769
604099
  const sid = f2.replace(/\.json$/, "");
603770
604100
  try {
603771
- const items = JSON.parse(readFileSync86(join122(dir, f2), "utf-8"));
604101
+ const items = JSON.parse(readFileSync86(join123(dir, f2), "utf-8"));
603772
604102
  if (Array.isArray(items)) {
603773
604103
  cache8.set(sid, new Map(items.map((t2) => [t2.id, t2])));
603774
604104
  }
@@ -603780,10 +604110,10 @@ function startApiServer(options2 = {}) {
603780
604110
  const watcher = fsWatch3(dir, (_evt, fname) => {
603781
604111
  if (!fname || !fname.endsWith(".json") || fname.includes(".tmp.")) return;
603782
604112
  const sid = fname.replace(/\.json$/, "");
603783
- const fp = join122(dir, fname);
604113
+ const fp = join123(dir, fname);
603784
604114
  let next = [];
603785
604115
  try {
603786
- if (!existsSync106(fp)) {
604116
+ if (!existsSync107(fp)) {
603787
604117
  const old = cache8.get(sid);
603788
604118
  if (old) {
603789
604119
  for (const t2 of old.values()) {
@@ -603835,13 +604165,13 @@ function startApiServer(options2 = {}) {
603835
604165
  const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
603836
604166
  if (retentionDays > 0) {
603837
604167
  try {
603838
- const jobsDir3 = join122(cwd4, ".oa", "jobs");
603839
- if (existsSync106(jobsDir3)) {
604168
+ const jobsDir3 = join123(cwd4, ".oa", "jobs");
604169
+ if (existsSync107(jobsDir3)) {
603840
604170
  const cutoff = Date.now() - retentionDays * 864e5;
603841
604171
  for (const f2 of readdirSync36(jobsDir3)) {
603842
604172
  if (!f2.endsWith(".json")) continue;
603843
604173
  try {
603844
- const jobPath = join122(jobsDir3, f2);
604174
+ const jobPath = join123(jobsDir3, f2);
603845
604175
  const job = JSON.parse(readFileSync86(jobPath, "utf-8"));
603846
604176
  const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
603847
604177
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
@@ -603874,8 +604204,8 @@ function startApiServer(options2 = {}) {
603874
604204
  }
603875
604205
  let runtimeAccessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
603876
604206
  try {
603877
- const accessFile = join122(homedir43(), ".open-agents", "access");
603878
- if (existsSync106(accessFile)) {
604207
+ const accessFile = join123(homedir43(), ".open-agents", "access");
604208
+ if (existsSync107(accessFile)) {
603879
604209
  const persisted = readFileSync86(accessFile, "utf8").trim();
603880
604210
  const resolved = resolveAccessMode(persisted, host);
603881
604211
  if (resolved) runtimeAccessMode = resolved;
@@ -603929,9 +604259,9 @@ function startApiServer(options2 = {}) {
603929
604259
  const previous = runtimeAccessMode;
603930
604260
  runtimeAccessMode = requested;
603931
604261
  try {
603932
- const dir = join122(homedir43(), ".open-agents");
603933
- mkdirSync63(dir, { recursive: true });
603934
- writeFileSync55(join122(dir, "access"), `${runtimeAccessMode}
604262
+ const dir = join123(homedir43(), ".open-agents");
604263
+ mkdirSync64(dir, { recursive: true });
604264
+ writeFileSync56(join123(dir, "access"), `${runtimeAccessMode}
603935
604265
  `, "utf8");
603936
604266
  } catch {
603937
604267
  }
@@ -604144,9 +604474,9 @@ function startApiServer(options2 = {}) {
604144
604474
  try {
604145
604475
  const { startEmbeddingWorkers: startEmbeddingWorkers2 } = await Promise.resolve().then(() => (init_embedding_workers(), embedding_workers_exports));
604146
604476
  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"));
604477
+ const dbBase = join123(cwd4, ".oa");
604478
+ const epStore = new mem.EpisodeStore(join123(dbBase, "memory.db"));
604479
+ const kg = new mem.TemporalGraph(join123(dbBase, "kg.db"));
604150
604480
  try {
604151
604481
  ensureEmbedDeps2();
604152
604482
  } catch {
@@ -604224,7 +604554,7 @@ function startApiServer(options2 = {}) {
604224
604554
  log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
604225
604555
  `);
604226
604556
  try {
604227
- const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: _exists, readFileSync: _rfs } = require3("node:fs");
604557
+ const { writeFileSync: writeFileSync60, mkdirSync: mkdirSync68, existsSync: _exists, readFileSync: _rfs } = require3("node:fs");
604228
604558
  const { join: _join } = require3("node:path");
604229
604559
  const { homedir: _homedir } = require3("node:os");
604230
604560
  const apiHint = JSON.stringify({
@@ -604254,8 +604584,8 @@ function startApiServer(options2 = {}) {
604254
604584
  let written = 0;
604255
604585
  for (const dir of dirSet) {
604256
604586
  try {
604257
- if (!_exists(dir)) mkdirSync67(dir, { recursive: true });
604258
- writeFileSync59(_join(dir, "api-port.json"), apiHint);
604587
+ if (!_exists(dir)) mkdirSync68(dir, { recursive: true });
604588
+ writeFileSync60(_join(dir, "api-port.json"), apiHint);
604259
604589
  written++;
604260
604590
  } catch {
604261
604591
  }
@@ -604266,6 +604596,80 @@ function startApiServer(options2 = {}) {
604266
604596
  log22(` WARN: api-port hint write failed: ${e2.message}
604267
604597
  `);
604268
604598
  }
604599
+ if (process.env["OA_AUTO_NEXUS"] !== "0") {
604600
+ (async () => {
604601
+ try {
604602
+ const { join: _j } = require3("node:path");
604603
+ const { homedir: _hd } = require3("node:os");
604604
+ const { existsSync: _ex, readFileSync: _rf, statSync: _st } = require3("node:fs");
604605
+ const { execSync: _ex2 } = require3("node:child_process");
604606
+ let chosenNexusDir = null;
604607
+ if (process.env["OA_NEXUS_DIR"]) chosenNexusDir = process.env["OA_NEXUS_DIR"];
604608
+ if (!chosenNexusDir) {
604609
+ try {
604610
+ const regPath = _j(_hd(), ".open-agents", "nexus-registry.json");
604611
+ if (_ex(regPath)) {
604612
+ const reg = JSON.parse(_rf(regPath, "utf-8"));
604613
+ for (const e2 of reg?.dirs || []) {
604614
+ const d2 = typeof e2 === "string" ? e2 : e2?.dir;
604615
+ if (typeof d2 === "string" && _ex(d2)) {
604616
+ chosenNexusDir = d2;
604617
+ break;
604618
+ }
604619
+ }
604620
+ }
604621
+ } catch {
604622
+ }
604623
+ }
604624
+ if (!chosenNexusDir) {
604625
+ try {
604626
+ const cmd = `find "${_hd()}" -maxdepth 4 -path '*/.oa/nexus' -type d 2>/dev/null | head -10`;
604627
+ const out = _ex2(cmd, { encoding: "utf-8", timeout: 2e3 }).trim();
604628
+ for (const ln of out.split("\n").filter(Boolean)) {
604629
+ if (_ex(_j(ln, "status.json"))) {
604630
+ chosenNexusDir = ln;
604631
+ break;
604632
+ }
604633
+ }
604634
+ if (!chosenNexusDir && out) chosenNexusDir = out.split("\n")[0]?.trim() || null;
604635
+ } catch {
604636
+ }
604637
+ }
604638
+ const finalNexusDir = chosenNexusDir ?? _j(_hd(), ".oa", "nexus");
604639
+ chosenNexusDir = finalNexusDir;
604640
+ const repoRoot = finalNexusDir.replace(/[\\/]\.oa[\\/]nexus$/, "");
604641
+ log22(` Nexus auto-recover: target ${finalNexusDir}
604642
+ `);
604643
+ const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
604644
+ const tool = new NexusTool2(repoRoot);
604645
+ const result = await tool.execute({ action: "connect" });
604646
+ const status = result?.success ? "ok" : "fail";
604647
+ const detail = result?.output || result?.error || "";
604648
+ log22(` Nexus auto-recover: ${status}${detail ? " — " + String(detail).split("\n")[0].slice(0, 120) : ""}
604649
+ `);
604650
+ if (status === "ok") {
604651
+ try {
604652
+ const { writeFileSync: _wfs2, mkdirSync: _mks, existsSync: _exf } = require3("node:fs");
604653
+ const apiHint2 = JSON.stringify({
604654
+ port,
604655
+ host: host === "0.0.0.0" ? "127.0.0.1" : host,
604656
+ scheme: proto,
604657
+ pid: process.pid,
604658
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
604659
+ version: version4
604660
+ }, null, 2);
604661
+ const dirOut = chosenNexusDir;
604662
+ if (!_exf(dirOut)) _mks(dirOut, { recursive: true });
604663
+ _wfs2(_j(dirOut, "api-port.json"), apiHint2);
604664
+ } catch {
604665
+ }
604666
+ }
604667
+ } catch (e2) {
604668
+ log22(` Nexus auto-recover: skipped (${e2.message.slice(0, 80)})
604669
+ `);
604670
+ }
604671
+ })();
604672
+ }
604269
604673
  try {
604270
604674
  adoptHandoffRuns();
604271
604675
  } catch (e2) {
@@ -604499,10 +604903,10 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
604499
604903
  const labels = Array.isArray(b.labels) ? b.labels : [];
604500
604904
  const mediaPath = typeof b.media_path === "string" ? b.media_path : void 0;
604501
604905
  const cwd4 = process.cwd();
604502
- const dbBase = join122(cwd4, ".oa");
604906
+ const dbBase = join123(cwd4, ".oa");
604503
604907
  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"));
604908
+ const epStore = new EpisodeStore3(join123(dbBase, "memory.db"));
604909
+ const kg = new TemporalGraph3(join123(dbBase, "kg.db"));
604506
604910
  const meta = {};
604507
604911
  if (mediaPath) meta.media_path = mediaPath;
604508
604912
  const epId = epStore.insert({ modality, content: content || (mediaPath || ""), metadata: meta, toolName: "memory_ingest" });
@@ -604569,7 +604973,7 @@ async function handleEntitiesList(req2, res) {
604569
604973
  const type = url.searchParams.get("type") || "person";
604570
604974
  const limit = Math.max(1, Math.min(1e3, parseInt(url.searchParams.get("limit") || "100", 10)));
604571
604975
  const { TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
604572
- const kg = new TemporalGraph3(join122(process.cwd(), ".oa", "kg.db"));
604976
+ const kg = new TemporalGraph3(join123(process.cwd(), ".oa", "kg.db"));
604573
604977
  const nodes = kg.nodesByType(type, limit).map((n2) => ({ id: n2.id, text: n2.text, mentionCount: n2.mentionCount, firstSeen: n2.firstSeen, lastSeen: n2.lastSeen }));
604574
604978
  jsonResponse(res, 200, { object: "list", data: nodes });
604575
604979
  } catch (err) {
@@ -604591,7 +604995,7 @@ async function handleMemorySearch2(req2, res) {
604591
604995
  const wLex = typeof b.lexical_weight === "number" ? b.lexical_weight : 1;
604592
604996
  const wEmb = typeof b.embedding_weight === "number" ? b.embedding_weight : 1;
604593
604997
  const { EpisodeStore: EpisodeStore3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
604594
- const epStore = new EpisodeStore3(join122(process.cwd(), ".oa", "memory.db"));
604998
+ const epStore = new EpisodeStore3(join123(process.cwd(), ".oa", "memory.db"));
604595
604999
  const results = epStore.search({ query, modality, limit }, { queryEmbedding: qEmb, lexicalWeight: wLex, embeddingWeight: wEmb });
604596
605000
  jsonResponse(res, 200, { object: "list", data: results.map((e2) => ({ id: e2.id, modality: e2.modality, content: e2.content, timestamp: e2.timestamp })) });
604597
605001
  } catch (err) {
@@ -604708,11 +605112,11 @@ var init_serve = __esm({
604708
605112
 
604709
605113
  // packages/cli/src/tui/interactive.ts
604710
605114
  import { cwd } from "node:process";
604711
- import { resolve as resolve39, join as join123, dirname as dirname37, extname as extname12 } from "node:path";
605115
+ import { resolve as resolve39, join as join124, dirname as dirname37, extname as extname12 } from "node:path";
604712
605116
  import { createRequire as createRequire6 } from "node:module";
604713
605117
  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";
605118
+ import { readFileSync as readFileSync87, writeFileSync as writeFileSync57, appendFileSync as appendFileSync8, rmSync as rmSync5, readdirSync as readdirSync37, mkdirSync as mkdirSync65 } from "node:fs";
605119
+ import { existsSync as existsSync108 } from "node:fs";
604716
605120
  import { execSync as execSync58 } from "node:child_process";
604717
605121
  import { homedir as homedir44 } from "node:os";
604718
605122
  function formatTimeAgo2(date) {
@@ -604730,12 +605134,12 @@ function getVersion4() {
604730
605134
  const require4 = createRequire6(import.meta.url);
604731
605135
  const thisDir = dirname37(fileURLToPath18(import.meta.url));
604732
605136
  const candidates = [
604733
- join123(thisDir, "..", "package.json"),
604734
- join123(thisDir, "..", "..", "package.json"),
604735
- join123(thisDir, "..", "..", "..", "package.json")
605137
+ join124(thisDir, "..", "package.json"),
605138
+ join124(thisDir, "..", "..", "package.json"),
605139
+ join124(thisDir, "..", "..", "..", "package.json")
604736
605140
  ];
604737
605141
  for (const pkgPath of candidates) {
604738
- if (existsSync107(pkgPath)) {
605142
+ if (existsSync108(pkgPath)) {
604739
605143
  const pkg = require4(pkgPath);
604740
605144
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
604741
605145
  return pkg.version ?? "0.0.0";
@@ -605541,14 +605945,14 @@ Meta-critique: quality ${meta.quality}/5, thorough: ${meta.thorough}`;
605541
605945
  function gatherMemorySnippets(root) {
605542
605946
  const snippets = [];
605543
605947
  const dirs = [
605544
- join123(root, ".oa", "memory"),
605545
- join123(root, ".open-agents", "memory")
605948
+ join124(root, ".oa", "memory"),
605949
+ join124(root, ".open-agents", "memory")
605546
605950
  ];
605547
605951
  for (const dir of dirs) {
605548
- if (!existsSync107(dir)) continue;
605952
+ if (!existsSync108(dir)) continue;
605549
605953
  try {
605550
605954
  for (const f2 of readdirSync37(dir).filter((f3) => f3.endsWith(".json"))) {
605551
- const data = JSON.parse(readFileSync87(join123(dir, f2), "utf-8"));
605955
+ const data = JSON.parse(readFileSync87(join124(dir, f2), "utf-8"));
605552
605956
  for (const val of Object.values(data)) {
605553
605957
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
605554
605958
  if (v.length > 10) snippets.push(v);
@@ -605702,8 +606106,8 @@ ${metabolismMemories}
605702
606106
  } catch {
605703
606107
  }
605704
606108
  try {
605705
- const archeFile = join123(repoRoot, ".oa", "arche", "variants.json");
605706
- if (existsSync107(archeFile)) {
606109
+ const archeFile = join124(repoRoot, ".oa", "arche", "variants.json");
606110
+ if (existsSync108(archeFile)) {
605707
606111
  const variants = JSON.parse(readFileSync87(archeFile, "utf8"));
605708
606112
  if (variants.length > 0) {
605709
606113
  let filtered = variants;
@@ -605876,8 +606280,8 @@ RULES:
605876
606280
  const compactionThreshold = Number.isFinite(envOverride) && envOverride > 0 ? envOverride : modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
605877
606281
  let identityInjection = "";
605878
606282
  try {
605879
- const ikStateFile = join123(repoRoot, ".oa", "identity", "self-state.json");
605880
- if (existsSync107(ikStateFile)) {
606283
+ const ikStateFile = join124(repoRoot, ".oa", "identity", "self-state.json");
606284
+ if (existsSync108(ikStateFile)) {
605881
606285
  const selfState = JSON.parse(readFileSync87(ikStateFile, "utf8"));
605882
606286
  const lines = [
605883
606287
  `[Identity State v${selfState.version}]`,
@@ -606740,13 +607144,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606740
607144
  });
606741
607145
  }
606742
607146
  try {
606743
- const ikDir = join123(repoRoot, ".oa", "identity");
606744
- const ikFile = join123(ikDir, "self-state.json");
607147
+ const ikDir = join124(repoRoot, ".oa", "identity");
607148
+ const ikFile = join124(ikDir, "self-state.json");
606745
607149
  let ikState;
606746
- if (existsSync107(ikFile)) {
607150
+ if (existsSync108(ikFile)) {
606747
607151
  ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
606748
607152
  } else {
606749
- mkdirSync64(ikDir, { recursive: true });
607153
+ mkdirSync65(ikDir, { recursive: true });
606750
607154
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
606751
607155
  ikState = {
606752
607156
  self_id: `oa-${machineId}`,
@@ -606802,7 +607206,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606802
607206
  }
606803
607207
  ikState.session_count = (ikState.session_count || 0) + 1;
606804
607208
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
606805
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
607209
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
606806
607210
  } catch (ikErr) {
606807
607211
  try {
606808
607212
  console.error("[IK-OBSERVE]", ikErr);
@@ -606821,8 +607225,8 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606821
607225
  } else {
606822
607226
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
606823
607227
  try {
606824
- const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
606825
- if (existsSync107(ikFile)) {
607228
+ const ikFile = join124(repoRoot, ".oa", "identity", "self-state.json");
607229
+ if (existsSync108(ikFile)) {
606826
607230
  const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
606827
607231
  if (!ikState.stats) ikState.stats = { queries_served: 0 };
606828
607232
  ikState.stats.queries_served = (ikState.stats.queries_served || 0) + 1;
@@ -606834,7 +607238,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
606834
607238
  if (ikState.version_history.length > 200) ikState.version_history = ikState.version_history.slice(-200);
606835
607239
  ikState.session_count = (ikState.session_count || 0) + 1;
606836
607240
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
606837
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
607241
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
606838
607242
  }
606839
607243
  } catch {
606840
607244
  }
@@ -607079,9 +607483,9 @@ async function startInteractive(config, repoPath) {
607079
607483
  process.stdin.pause();
607080
607484
  }
607081
607485
  try {
607082
- const oaDir = join123(repoRoot, ".oa");
607083
- const nexusPidFile = join123(oaDir, "nexus", "daemon.pid");
607084
- if (existsSync107(nexusPidFile)) {
607486
+ const oaDir = join124(repoRoot, ".oa");
607487
+ const nexusPidFile = join124(oaDir, "nexus", "daemon.pid");
607488
+ if (existsSync108(nexusPidFile)) {
607085
607489
  const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
607086
607490
  if (pid > 0) {
607087
607491
  try {
@@ -607742,7 +608146,7 @@ ${result.summary}`
607742
608146
  let p2pGateway = null;
607743
608147
  let peerMesh = null;
607744
608148
  let inferenceRouter = null;
607745
- const secretVault = new SecretVault(join123(repoRoot, ".oa", "vault.enc"));
608149
+ const secretVault = new SecretVault(join124(repoRoot, ".oa", "vault.enc"));
607746
608150
  let adminSessionKey = null;
607747
608151
  const callSubAgents = /* @__PURE__ */ new Map();
607748
608152
  const streamRenderer = new StreamRenderer();
@@ -607973,12 +608377,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
607973
608377
  const hits = allCompletions.filter((c9) => c9.toLowerCase().startsWith(lower));
607974
608378
  return [hits, line];
607975
608379
  }
607976
- const HISTORY_DIR = join123(homedir44(), ".open-agents");
607977
- const HISTORY_FILE = join123(HISTORY_DIR, "repl-history");
608380
+ const HISTORY_DIR = join124(homedir44(), ".open-agents");
608381
+ const HISTORY_FILE = join124(HISTORY_DIR, "repl-history");
607978
608382
  const MAX_HISTORY_LINES = 500;
607979
608383
  let savedHistory = [];
607980
608384
  try {
607981
- if (existsSync107(HISTORY_FILE)) {
608385
+ if (existsSync108(HISTORY_FILE)) {
607982
608386
  const raw = readFileSync87(HISTORY_FILE, "utf8").trim();
607983
608387
  if (raw) savedHistory = raw.split("\n").reverse();
607984
608388
  }
@@ -608126,12 +608530,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608126
608530
  function persistHistoryLine(line) {
608127
608531
  if (!line.trim()) return;
608128
608532
  try {
608129
- mkdirSync64(HISTORY_DIR, { recursive: true });
608533
+ mkdirSync65(HISTORY_DIR, { recursive: true });
608130
608534
  appendFileSync8(HISTORY_FILE, line + "\n", "utf8");
608131
608535
  if (Math.random() < 0.02) {
608132
608536
  const all2 = readFileSync87(HISTORY_FILE, "utf8").trim().split("\n");
608133
608537
  if (all2.length > MAX_HISTORY_LINES) {
608134
- writeFileSync56(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
608538
+ writeFileSync57(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
608135
608539
  }
608136
608540
  }
608137
608541
  } catch {
@@ -608316,10 +608720,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608316
608720
  const { unlinkSync: _rmStale } = await import("node:fs");
608317
608721
  const { homedir: _hdir } = await import("node:os");
608318
608722
  for (const dp of [
608319
- join123(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
608320
- join123(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
608723
+ join124(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
608724
+ join124(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
608321
608725
  ]) {
608322
- if (existsSync107(dp)) try {
608726
+ if (existsSync108(dp)) try {
608323
608727
  _rmStale(dp);
608324
608728
  } catch {
608325
608729
  }
@@ -608330,8 +608734,8 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608330
608734
  const autoNexus = new NexusTool(repoRoot);
608331
608735
  const _registerNexusDaemon = () => {
608332
608736
  try {
608333
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
608334
- if (existsSync107(nexusPidFile)) {
608737
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
608738
+ if (existsSync108(nexusPidFile)) {
608335
608739
  const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
608336
608740
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
608337
608741
  registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
@@ -608389,7 +608793,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608389
608793
  } catch {
608390
608794
  }
608391
608795
  try {
608392
- const oaDir = join123(repoRoot, ".oa");
608796
+ const oaDir = join124(repoRoot, ".oa");
608393
608797
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
608394
608798
  onInfo: (msg) => writeContent(() => renderInfo2(msg)),
608395
608799
  onError: (msg) => writeContent(() => renderWarning2(msg))
@@ -608421,7 +608825,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608421
608825
  } catch {
608422
608826
  }
608423
608827
  try {
608424
- const oaDir = join123(repoRoot, ".oa");
608828
+ const oaDir = join124(repoRoot, ".oa");
608425
608829
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
608426
608830
  onInfo: (msg) => writeContent(() => renderInfo2(msg)),
608427
608831
  onError: (msg) => writeContent(() => renderWarning2(msg))
@@ -608462,10 +608866,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608462
608866
  }
608463
608867
  try {
608464
608868
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
608465
- const globalNamePath = join123(_hd(), ".open-agents", "agent-name");
608869
+ const globalNamePath = join124(_hd(), ".open-agents", "agent-name");
608466
608870
  let agName = "";
608467
608871
  try {
608468
- if (existsSync107(globalNamePath)) agName = readFileSync87(globalNamePath, "utf8").trim();
608872
+ if (existsSync108(globalNamePath)) agName = readFileSync87(globalNamePath, "utf8").trim();
608469
608873
  } catch {
608470
608874
  }
608471
608875
  if (!agName) {
@@ -608494,10 +608898,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
608494
608898
  }
608495
608899
  if (!ollamaAlive) {
608496
608900
  try {
608497
- const savedSponsorsPath = join123(repoRoot, ".oa", "sponsor", "known-sponsors.json");
608901
+ const savedSponsorsPath = join124(repoRoot, ".oa", "sponsor", "known-sponsors.json");
608498
608902
  let savedSponsors = [];
608499
608903
  try {
608500
- if (existsSync107(savedSponsorsPath)) {
608904
+ if (existsSync108(savedSponsorsPath)) {
608501
608905
  savedSponsors = JSON.parse(readFileSync87(savedSponsorsPath, "utf8"));
608502
608906
  const oneHourAgo = Date.now() - 36e5;
608503
608907
  savedSponsors = savedSponsors.filter((s2) => (s2.lastVerified || 0) > oneHourAgo);
@@ -609590,10 +609994,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609590
609994
  if (name10 === "voice_list_files") {
609591
609995
  const baseDir = String(args?.dir ?? ".");
609592
609996
  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));
609997
+ const { join: join129, resolve: resolve43 } = __require("node:path");
609998
+ const base3 = baseDir.startsWith("/") ? baseDir : resolve43(join129(repoRoot, baseDir));
609595
609999
  const items = readdirSync39(base3).slice(0, 200).map((f2) => {
609596
- const s2 = statSync36(join128(base3, f2));
610000
+ const s2 = statSync36(join129(base3, f2));
609597
610001
  return { name: f2, dir: s2.isDirectory(), size: s2.size };
609598
610002
  });
609599
610003
  return JSON.stringify({ dir: base3, items }, null, 2);
@@ -609681,7 +610085,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609681
610085
  kind,
609682
610086
  targetUrl,
609683
610087
  authKey,
609684
- stateDir: join123(repoRoot, ".oa"),
610088
+ stateDir: join124(repoRoot, ".oa"),
609685
610089
  passthrough: passthrough ?? false,
609686
610090
  loadbalance: loadbalance ?? false,
609687
610091
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -609727,7 +610131,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609727
610131
  await tunnelGateway.stop();
609728
610132
  tunnelGateway = null;
609729
610133
  }
609730
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join123(repoRoot, ".oa") });
610134
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join124(repoRoot, ".oa") });
609731
610135
  newTunnel.on("stats", (stats) => {
609732
610136
  statusBar.setExposeStatus({
609733
610137
  status: stats.status,
@@ -609748,14 +610152,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609748
610152
  throw err;
609749
610153
  }
609750
610154
  },
609751
- async exposeStop(which) {
609752
- if (!which || which === "tunnel") {
610155
+ async exposeStop(which2) {
610156
+ if (!which2 || which2 === "tunnel") {
609753
610157
  if (tunnelGateway) {
609754
610158
  await tunnelGateway.stop();
609755
610159
  tunnelGateway = null;
609756
610160
  }
609757
610161
  }
609758
- if (!which || which === "libp2p") {
610162
+ if (!which2 || which2 === "libp2p") {
609759
610163
  if (p2pGateway) {
609760
610164
  await p2pGateway.stop();
609761
610165
  p2pGateway = null;
@@ -609814,8 +610218,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
609814
610218
  });
609815
610219
  if (!result.success) throw new Error(result.error || "Connect failed");
609816
610220
  try {
609817
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
609818
- if (existsSync107(nexusPidFile)) {
610221
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
610222
+ if (existsSync108(nexusPidFile)) {
609819
610223
  const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
609820
610224
  if (pid > 0) {
609821
610225
  registry2.register({
@@ -610004,9 +610408,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610004
610408
  writeContent(() => renderInfo2(`Killed ${bgKilled} background task(s).`));
610005
610409
  }
610006
610410
  try {
610007
- const nexusDir = join123(repoRoot, OA_DIR, "nexus");
610008
- const pidFile = join123(nexusDir, "daemon.pid");
610009
- if (existsSync107(pidFile)) {
610411
+ const nexusDir = join124(repoRoot, OA_DIR, "nexus");
610412
+ const pidFile = join124(nexusDir, "daemon.pid");
610413
+ if (existsSync108(pidFile)) {
610010
610414
  const pid = parseInt(readFileSync87(pidFile, "utf8").trim(), 10);
610011
610415
  if (pid > 0) {
610012
610416
  try {
@@ -610029,11 +610433,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610029
610433
  } catch {
610030
610434
  }
610031
610435
  try {
610032
- const voiceDir2 = join123(homedir44(), ".open-agents", "voice");
610436
+ const voiceDir2 = join124(homedir44(), ".open-agents", "voice");
610033
610437
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
610034
610438
  for (const pf of voicePidFiles) {
610035
- const pidPath = join123(voiceDir2, pf);
610036
- if (existsSync107(pidPath)) {
610439
+ const pidPath = join124(voiceDir2, pf);
610440
+ if (existsSync108(pidPath)) {
610037
610441
  try {
610038
610442
  const pid = parseInt(readFileSync87(pidPath, "utf8").trim(), 10);
610039
610443
  if (pid > 0) {
@@ -610059,8 +610463,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610059
610463
  execSync58(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
610060
610464
  } catch {
610061
610465
  }
610062
- const oaPath = join123(repoRoot, OA_DIR);
610063
- if (existsSync107(oaPath)) {
610466
+ const oaPath = join124(repoRoot, OA_DIR);
610467
+ if (existsSync108(oaPath)) {
610064
610468
  let deleted = false;
610065
610469
  for (let attempt = 0; attempt < 3; attempt++) {
610066
610470
  try {
@@ -610144,18 +610548,18 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
610144
610548
  try {
610145
610549
  const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
610146
610550
  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)) {
610551
+ const ppPidFile = join124(homedir44(), ".open-agents", "voice", "personaplex", "daemon.pid");
610552
+ const ppPortFile = join124(homedir44(), ".open-agents", "voice", "personaplex", "daemon.port");
610553
+ if (existsSync108(ppPidFile)) {
610150
610554
  const ppPid = parseInt(readFileSync87(ppPidFile, "utf8").trim(), 10);
610151
- const ppPort = existsSync107(ppPortFile) ? parseInt(readFileSync87(ppPortFile, "utf8").trim(), 10) : void 0;
610555
+ const ppPort = existsSync108(ppPortFile) ? parseInt(readFileSync87(ppPortFile, "utf8").trim(), 10) : void 0;
610152
610556
  if (ppPid > 0 && !registry2.daemons.has("PersonaPlex")) {
610153
610557
  registry2.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
610154
610558
  }
610155
610559
  }
610156
610560
  }
610157
- const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
610158
- if (existsSync107(nexusPidFile)) {
610561
+ const nexusPidFile = join124(repoRoot, ".oa", "nexus", "daemon.pid");
610562
+ if (existsSync108(nexusPidFile)) {
610159
610563
  const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
610160
610564
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
610161
610565
  try {
@@ -610523,9 +610927,9 @@ Execute this skill now. Follow the behavioral guidance above.`;
610523
610927
  }
610524
610928
  }
610525
610929
  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));
610930
+ const isImage = isImagePath(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610931
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610932
+ const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync108(resolve39(repoRoot, cleanPath));
610529
610933
  if (activeTask) {
610530
610934
  if (activeTask.runner.isPaused) {
610531
610935
  activeTask.runner.resume();
@@ -611112,13 +611516,13 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611112
611516
  const handle2 = startTask(task, config, repoRoot);
611113
611517
  await handle2.promise;
611114
611518
  try {
611115
- const ikDir = join123(repoRoot, ".oa", "identity");
611116
- const ikFile = join123(ikDir, "self-state.json");
611519
+ const ikDir = join124(repoRoot, ".oa", "identity");
611520
+ const ikFile = join124(ikDir, "self-state.json");
611117
611521
  let ikState;
611118
- if (existsSync107(ikFile)) {
611522
+ if (existsSync108(ikFile)) {
611119
611523
  ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
611120
611524
  } else {
611121
- mkdirSync64(ikDir, { recursive: true });
611525
+ mkdirSync65(ikDir, { recursive: true });
611122
611526
  ikState = {
611123
611527
  self_id: `oa-${Date.now().toString(36)}`,
611124
611528
  version: 1,
@@ -611140,7 +611544,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611140
611544
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
611141
611545
  ikState.session_count = (ikState.session_count || 0) + 1;
611142
611546
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
611143
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
611547
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
611144
611548
  } catch (ikErr) {
611145
611549
  }
611146
611550
  try {
@@ -611153,11 +611557,11 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611153
611557
  );
611154
611558
  } catch {
611155
611559
  try {
611156
- const archeDir = join123(repoRoot, ".oa", "arche");
611157
- const archeFile = join123(archeDir, "variants.json");
611560
+ const archeDir = join124(repoRoot, ".oa", "arche");
611561
+ const archeFile = join124(archeDir, "variants.json");
611158
611562
  let variants = [];
611159
611563
  try {
611160
- if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611564
+ if (existsSync108(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611161
611565
  } catch {
611162
611566
  }
611163
611567
  variants.push({
@@ -611171,14 +611575,14 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611171
611575
  tags: ["general"]
611172
611576
  });
611173
611577
  if (variants.length > 50) variants = variants.slice(-50);
611174
- mkdirSync64(archeDir, { recursive: true });
611175
- writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
611578
+ mkdirSync65(archeDir, { recursive: true });
611579
+ writeFileSync57(archeFile, JSON.stringify(variants, null, 2));
611176
611580
  } catch {
611177
611581
  }
611178
611582
  }
611179
611583
  try {
611180
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611181
- if (existsSync107(metaFile)) {
611584
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611585
+ if (existsSync108(metaFile)) {
611182
611586
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611183
611587
  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
611588
  let updated = false;
@@ -611190,7 +611594,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
611190
611594
  updated = true;
611191
611595
  }
611192
611596
  if (updated) {
611193
- writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
611597
+ writeFileSync57(metaFile, JSON.stringify(store2, null, 2));
611194
611598
  }
611195
611599
  }
611196
611600
  } catch {
@@ -611243,9 +611647,9 @@ Rules:
611243
611647
  try {
611244
611648
  const { initDb: initDb2 } = __require("@open-agents/memory");
611245
611649
  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"));
611650
+ const dbDir = join124(repoRoot, ".oa", "memory");
611651
+ mkdirSync65(dbDir, { recursive: true });
611652
+ const db = initDb2(join124(dbDir, "structured.db"));
611249
611653
  const memStore = new ProceduralMemoryStore2(db);
611250
611654
  memStore.createWithEmbedding({
611251
611655
  content: content.slice(0, 600),
@@ -611260,11 +611664,11 @@ Rules:
611260
611664
  db.close();
611261
611665
  } catch {
611262
611666
  }
611263
- const metaDir = join123(repoRoot, ".oa", "memory", "metabolism");
611264
- const storeFile = join123(metaDir, "store.json");
611667
+ const metaDir = join124(repoRoot, ".oa", "memory", "metabolism");
611668
+ const storeFile = join124(metaDir, "store.json");
611265
611669
  let store2 = [];
611266
611670
  try {
611267
- if (existsSync107(storeFile)) store2 = JSON.parse(readFileSync87(storeFile, "utf8"));
611671
+ if (existsSync108(storeFile)) store2 = JSON.parse(readFileSync87(storeFile, "utf8"));
611268
611672
  } catch {
611269
611673
  }
611270
611674
  store2.push({
@@ -611279,25 +611683,25 @@ Rules:
611279
611683
  accessCount: 0
611280
611684
  });
611281
611685
  if (store2.length > 100) store2 = store2.slice(-100);
611282
- mkdirSync64(metaDir, { recursive: true });
611283
- writeFileSync56(storeFile, JSON.stringify(store2, null, 2));
611686
+ mkdirSync65(metaDir, { recursive: true });
611687
+ writeFileSync57(storeFile, JSON.stringify(store2, null, 2));
611284
611688
  }
611285
611689
  }
611286
611690
  } catch {
611287
611691
  }
611288
611692
  try {
611289
- const cohereSettingsFile = join123(repoRoot, ".oa", "settings.json");
611693
+ const cohereSettingsFile = join124(repoRoot, ".oa", "settings.json");
611290
611694
  let cohereActive = false;
611291
611695
  try {
611292
- if (existsSync107(cohereSettingsFile)) {
611696
+ if (existsSync108(cohereSettingsFile)) {
611293
611697
  const settings = JSON.parse(readFileSync87(cohereSettingsFile, "utf8"));
611294
611698
  cohereActive = settings.cohere === true;
611295
611699
  }
611296
611700
  } catch {
611297
611701
  }
611298
611702
  if (cohereActive) {
611299
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611300
- if (existsSync107(metaFile)) {
611703
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611704
+ if (existsSync108(metaFile)) {
611301
611705
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611302
611706
  const latest = store2.filter((m2) => m2.sourceTrace === "trajectory-extraction" || m2.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
611303
611707
  if (latest && latest.scores?.confidence >= 0.6) {
@@ -611323,17 +611727,17 @@ Rules:
611323
611727
  }
611324
611728
  } catch (err) {
611325
611729
  try {
611326
- const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
611327
- if (existsSync107(ikFile)) {
611730
+ const ikFile = join124(repoRoot, ".oa", "identity", "self-state.json");
611731
+ if (existsSync108(ikFile)) {
611328
611732
  const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
611329
611733
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
611330
611734
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
611331
611735
  ikState.session_count = (ikState.session_count || 0) + 1;
611332
611736
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
611333
- writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
611737
+ writeFileSync57(ikFile, JSON.stringify(ikState, null, 2));
611334
611738
  }
611335
- const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
611336
- if (existsSync107(metaFile)) {
611739
+ const metaFile = join124(repoRoot, ".oa", "memory", "metabolism", "store.json");
611740
+ if (existsSync108(metaFile)) {
611337
611741
  const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
611338
611742
  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
611743
  for (const item of surfaced) {
@@ -611342,14 +611746,14 @@ Rules:
611342
611746
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
611343
611747
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
611344
611748
  }
611345
- writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
611749
+ writeFileSync57(metaFile, JSON.stringify(store2, null, 2));
611346
611750
  }
611347
611751
  try {
611348
- const archeDir = join123(repoRoot, ".oa", "arche");
611349
- const archeFile = join123(archeDir, "variants.json");
611752
+ const archeDir = join124(repoRoot, ".oa", "arche");
611753
+ const archeFile = join124(archeDir, "variants.json");
611350
611754
  let variants = [];
611351
611755
  try {
611352
- if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611756
+ if (existsSync108(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
611353
611757
  } catch {
611354
611758
  }
611355
611759
  variants.push({
@@ -611363,8 +611767,8 @@ Rules:
611363
611767
  tags: ["general"]
611364
611768
  });
611365
611769
  if (variants.length > 50) variants = variants.slice(-50);
611366
- mkdirSync64(archeDir, { recursive: true });
611367
- writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
611770
+ mkdirSync65(archeDir, { recursive: true });
611771
+ writeFileSync57(archeFile, JSON.stringify(variants, null, 2));
611368
611772
  } catch {
611369
611773
  }
611370
611774
  } catch {
@@ -611452,14 +611856,14 @@ __export(run_exports, {
611452
611856
  statusCommand: () => statusCommand
611453
611857
  });
611454
611858
  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";
611859
+ import { spawn as spawn27 } from "node:child_process";
611860
+ import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58, readFileSync as readFileSync88, readdirSync as readdirSync38, existsSync as existsSync109 } from "node:fs";
611457
611861
  import { randomBytes as randomBytes24 } from "node:crypto";
611458
- import { join as join124 } from "node:path";
611862
+ import { join as join125 } from "node:path";
611459
611863
  function jobsDir2(repoPath) {
611460
611864
  const root = resolve40(repoPath ?? process.cwd());
611461
- const dir = join124(root, ".oa", "jobs");
611462
- mkdirSync65(dir, { recursive: true });
611865
+ const dir = join125(root, ".oa", "jobs");
611866
+ mkdirSync66(dir, { recursive: true });
611463
611867
  return dir;
611464
611868
  }
611465
611869
  async function runCommand(opts, config) {
@@ -611565,7 +611969,7 @@ async function runBackground(task, config, opts) {
611565
611969
  const oaBin = process.argv[1] || "oa";
611566
611970
  const args = [task, "--json"];
611567
611971
  if (config.model) args.push("--model", config.model);
611568
- const child = spawn26(process.execPath, [oaBin, ...args], {
611972
+ const child = spawn27(process.execPath, [oaBin, ...args], {
611569
611973
  cwd: repoRoot,
611570
611974
  env: { ...process.env, OA_JOB_ID: id },
611571
611975
  stdio: ["ignore", "pipe", "pipe"],
@@ -611581,7 +611985,7 @@ async function runBackground(task, config, opts) {
611581
611985
  }
611582
611986
  });
611583
611987
  job.pid = child.pid ?? 0;
611584
- writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
611988
+ writeFileSync58(join125(dir, `${id}.json`), JSON.stringify(job, null, 2));
611585
611989
  let output = "";
611586
611990
  child.stdout?.on("data", (chunk) => {
611587
611991
  output += chunk.toString();
@@ -611597,7 +612001,7 @@ async function runBackground(task, config, opts) {
611597
612001
  job.summary = result.summary;
611598
612002
  job.durationMs = result.durationMs;
611599
612003
  job.error = result.error;
611600
- writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
612004
+ writeFileSync58(join125(dir, `${id}.json`), JSON.stringify(job, null, 2));
611601
612005
  } catch {
611602
612006
  }
611603
612007
  });
@@ -611613,8 +612017,8 @@ async function runBackground(task, config, opts) {
611613
612017
  }
611614
612018
  function statusCommand(jobId, repoPath) {
611615
612019
  const dir = jobsDir2(repoPath);
611616
- const file = join124(dir, `${jobId}.json`);
611617
- if (!existsSync108(file)) {
612020
+ const file = join125(dir, `${jobId}.json`);
612021
+ if (!existsSync109(file)) {
611618
612022
  console.error(`Job not found: ${jobId}`);
611619
612023
  console.log(`Available jobs: oa jobs`);
611620
612024
  process.exit(1);
@@ -611640,7 +612044,7 @@ function jobsCommand(repoPath) {
611640
612044
  console.log("Jobs:");
611641
612045
  for (const file of files) {
611642
612046
  try {
611643
- const job = JSON.parse(readFileSync88(join124(dir, file), "utf-8"));
612047
+ const job = JSON.parse(readFileSync88(join125(dir, file), "utf-8"));
611644
612048
  const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
611645
612049
  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
612050
  const cleanListTask = cleanForStorage(job.task) || job.task;
@@ -611664,13 +612068,13 @@ __export(index_repo_exports, {
611664
612068
  indexRepoCommand: () => indexRepoCommand
611665
612069
  });
611666
612070
  import { resolve as resolve41 } from "node:path";
611667
- import { existsSync as existsSync109, statSync as statSync35 } from "node:fs";
612071
+ import { existsSync as existsSync110, statSync as statSync35 } from "node:fs";
611668
612072
  import { cwd as cwd2 } from "node:process";
611669
612073
  async function indexRepoCommand(opts, _config3) {
611670
612074
  const repoRoot = resolve41(opts.repoPath ?? cwd2());
611671
612075
  printHeader("Index Repository");
611672
612076
  printInfo(`Indexing: ${repoRoot}`);
611673
- if (!existsSync109(repoRoot)) {
612077
+ if (!existsSync110(repoRoot)) {
611674
612078
  printError(`Path does not exist: ${repoRoot}`);
611675
612079
  process.exit(1);
611676
612080
  }
@@ -611922,7 +612326,7 @@ var config_exports2 = {};
611922
612326
  __export(config_exports2, {
611923
612327
  configCommand: () => configCommand
611924
612328
  });
611925
- import { join as join125, resolve as resolve42 } from "node:path";
612329
+ import { join as join126, resolve as resolve42 } from "node:path";
611926
612330
  import { homedir as homedir45 } from "node:os";
611927
612331
  import { cwd as cwd3 } from "node:process";
611928
612332
  function redactIfSensitive(key, value2) {
@@ -612004,7 +612408,7 @@ function handleShow(opts, config) {
612004
612408
  }
612005
612409
  }
612006
612410
  printSection("Config File");
612007
- printInfo(`~/.open-agents/config.json (${join125(homedir45(), ".open-agents", "config.json")})`);
612411
+ printInfo(`~/.open-agents/config.json (${join126(homedir45(), ".open-agents", "config.json")})`);
612008
612412
  printSection("Priority Chain");
612009
612413
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
612010
612414
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -612043,7 +612447,7 @@ function handleSet(opts, _config3) {
612043
612447
  const coerced = coerceForSettings(key, value2);
612044
612448
  saveProjectSettings(repoRoot, { [key]: coerced });
612045
612449
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value2)}`);
612046
- printInfo(`Saved to ${join125(repoRoot, ".oa", "settings.json")}`);
612450
+ printInfo(`Saved to ${join126(repoRoot, ".oa", "settings.json")}`);
612047
612451
  printInfo("This override applies only when running in this workspace.");
612048
612452
  } catch (err) {
612049
612453
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -612226,9 +612630,9 @@ var eval_exports = {};
612226
612630
  __export(eval_exports, {
612227
612631
  evalCommand: () => evalCommand
612228
612632
  });
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";
612633
+ import { tmpdir as tmpdir22 } from "node:os";
612634
+ import { mkdirSync as mkdirSync67, writeFileSync as writeFileSync59 } from "node:fs";
612635
+ import { join as join127 } from "node:path";
612232
612636
  async function evalCommand(opts, config) {
612233
612637
  const suiteName = opts.suite ?? "basic";
612234
612638
  const suite = SUITES[suiteName];
@@ -612357,10 +612761,10 @@ async function evalCommand(opts, config) {
612357
612761
  process.exit(failed > 0 ? 1 : 0);
612358
612762
  }
612359
612763
  function createTempEvalRepo() {
612360
- const dir = join126(tmpdir21(), `open-agents-eval-${Date.now()}`);
612361
- mkdirSync66(dir, { recursive: true });
612362
- writeFileSync58(
612363
- join126(dir, "package.json"),
612764
+ const dir = join127(tmpdir22(), `open-agents-eval-${Date.now()}`);
612765
+ mkdirSync67(dir, { recursive: true });
612766
+ writeFileSync59(
612767
+ join127(dir, "package.json"),
612364
612768
  JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
612365
612769
  "utf8"
612366
612770
  );
@@ -612424,7 +612828,7 @@ init_typed_node_events();
612424
612828
  import { parseArgs as nodeParseArgs2 } from "node:util";
612425
612829
  import { createRequire as createRequire7 } from "node:module";
612426
612830
  import { fileURLToPath as fileURLToPath19 } from "node:url";
612427
- import { dirname as dirname38, join as join127 } from "node:path";
612831
+ import { dirname as dirname38, join as join128 } from "node:path";
612428
612832
 
612429
612833
  // packages/cli/src/cli.ts
612430
612834
  init_typed_node_events();
@@ -612564,7 +612968,7 @@ init_output();
612564
612968
  function getVersion5() {
612565
612969
  try {
612566
612970
  const require4 = createRequire7(import.meta.url);
612567
- const pkgPath = join127(dirname38(fileURLToPath19(import.meta.url)), "..", "package.json");
612971
+ const pkgPath = join128(dirname38(fileURLToPath19(import.meta.url)), "..", "package.json");
612568
612972
  const pkg = require4(pkgPath);
612569
612973
  return pkg.version;
612570
612974
  } catch {
@@ -612753,9 +613157,9 @@ async function main() {
612753
613157
  const mode = process.argv[process.argv.indexOf("--self-test") + 1] || "crossmodal";
612754
613158
  if (mode === "crossmodal") {
612755
613159
  process.stdout.write("Running crossmodal smoke tests...\n");
612756
- const { spawn: spawn27 } = await import("node:child_process");
613160
+ const { spawn: spawn28 } = await import("node:child_process");
612757
613161
  const run = (file) => new Promise((resolve43, reject) => {
612758
- const p2 = spawn27(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
613162
+ const p2 = spawn28(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
612759
613163
  p2.stdout.on("data", (d2) => process.stdout.write(d2));
612760
613164
  p2.stderr.on("data", (d2) => process.stdout.write(d2));
612761
613165
  onChildExit(p2, (code8) => code8 === 0 ? resolve43() : reject(new Error(`${file} exited ${code8}`)));
@@ -612878,12 +613282,12 @@ function crashLog(label, err) {
612878
613282
  const logLine = `[${timestamp}] ${label}: ${msg}
612879
613283
  `;
612880
613284
  try {
612881
- const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync67 } = __require("node:fs");
612882
- const { join: join128 } = __require("node:path");
613285
+ const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync68 } = __require("node:fs");
613286
+ const { join: join129 } = __require("node:path");
612883
613287
  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);
613288
+ const logDir = join129(homedir46(), ".open-agents");
613289
+ mkdirSync68(logDir, { recursive: true });
613290
+ appendFileSync9(join129(logDir, "crash.log"), logLine);
612887
613291
  } catch {
612888
613292
  }
612889
613293
  try {