open-agents-ai 0.184.1 → 0.184.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1094 -502
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -61,11 +61,11 @@ function parseBackendType(value) {
61
61
  return VALID_BACKEND_TYPES.has(value) ? value : void 0;
62
62
  }
63
63
  function loadConfigFile() {
64
- const configPath = join(homedir(), ".open-agents", "config.json");
65
- if (!existsSync(configPath))
64
+ const configPath2 = join(homedir(), ".open-agents", "config.json");
65
+ if (!existsSync(configPath2))
66
66
  return {};
67
67
  try {
68
- const raw = readFileSync(configPath, "utf8");
68
+ const raw = readFileSync(configPath2, "utf8");
69
69
  const parsed = JSON.parse(raw);
70
70
  const result = {};
71
71
  if (typeof parsed.backendUrl === "string")
@@ -111,10 +111,10 @@ function mergeConfig(base, overrides) {
111
111
  function setConfigValue(key, value) {
112
112
  const dir = join(homedir(), ".open-agents");
113
113
  mkdirSync(dir, { recursive: true });
114
- const configPath = join(dir, "config.json");
114
+ const configPath2 = join(dir, "config.json");
115
115
  const existing = loadConfigFile();
116
116
  existing[key] = coerceConfigValue(key, value);
117
- writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n", { encoding: "utf8", mode: 384 });
117
+ writeFileSync(configPath2, JSON.stringify(existing, null, 2) + "\n", { encoding: "utf8", mode: 384 });
118
118
  }
119
119
  function coerceConfigValue(key, value) {
120
120
  const intKeys = /* @__PURE__ */ new Set(["maxRetries", "timeoutMs"]);
@@ -13402,9 +13402,9 @@ print("${sentinel}")
13402
13402
  if (!this.proc || this.proc.killed) {
13403
13403
  return { success: false, path: "" };
13404
13404
  }
13405
- const { mkdirSync: mkdirSync26, writeFileSync: writeFileSync25 } = await import("node:fs");
13405
+ const { mkdirSync: mkdirSync27, writeFileSync: writeFileSync26 } = await import("node:fs");
13406
13406
  const sessionDir = join22(this.cwd, ".oa", "rlm");
13407
- mkdirSync26(sessionDir, { recursive: true });
13407
+ mkdirSync27(sessionDir, { recursive: true });
13408
13408
  const sessionPath = join22(sessionDir, "session.json");
13409
13409
  try {
13410
13410
  const inspectCode = `
@@ -13428,7 +13428,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13428
13428
  trajectoryCount: this.trajectory.length,
13429
13429
  subCallCount: this.subCallCount
13430
13430
  };
13431
- writeFileSync25(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13431
+ writeFileSync26(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13432
13432
  return { success: true, path: sessionPath };
13433
13433
  }
13434
13434
  } catch {
@@ -13440,11 +13440,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13440
13440
  * what was previously computed. */
13441
13441
  async loadSessionInfo() {
13442
13442
  try {
13443
- const { readFileSync: readFileSync40, existsSync: existsSync52 } = await import("node:fs");
13443
+ const { readFileSync: readFileSync41, existsSync: existsSync53 } = await import("node:fs");
13444
13444
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13445
- if (!existsSync52(sessionPath))
13445
+ if (!existsSync53(sessionPath))
13446
13446
  return null;
13447
- return JSON.parse(readFileSync40(sessionPath, "utf8"));
13447
+ return JSON.parse(readFileSync41(sessionPath, "utf8"));
13448
13448
  } catch {
13449
13449
  return null;
13450
13450
  }
@@ -13621,10 +13621,10 @@ var init_memory_metabolism = __esm({
13621
13621
  const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
13622
13622
  let lessons = [];
13623
13623
  try {
13624
- const { readdirSync: readdirSync21, readFileSync: readFileSync40 } = await import("node:fs");
13624
+ const { readdirSync: readdirSync21, readFileSync: readFileSync41 } = await import("node:fs");
13625
13625
  const files = readdirSync21(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
13626
13626
  for (const file of files) {
13627
- const lines = readFileSync40(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13627
+ const lines = readFileSync41(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13628
13628
  for (const line of lines) {
13629
13629
  try {
13630
13630
  const entry = JSON.parse(line);
@@ -14008,14 +14008,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14008
14008
  * Optionally filter by task type for phase-aware context (FSM paper insight).
14009
14009
  */
14010
14010
  getTopMemoriesSync(k = 5, taskType) {
14011
- const { readFileSync: readFileSync40, existsSync: existsSync52 } = __require("node:fs");
14011
+ const { readFileSync: readFileSync41, existsSync: existsSync53 } = __require("node:fs");
14012
14012
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14013
14013
  const storeFile = join23(metaDir, "store.json");
14014
- if (!existsSync52(storeFile))
14014
+ if (!existsSync53(storeFile))
14015
14015
  return "";
14016
14016
  let store = [];
14017
14017
  try {
14018
- store = JSON.parse(readFileSync40(storeFile, "utf8"));
14018
+ store = JSON.parse(readFileSync41(storeFile, "utf8"));
14019
14019
  } catch {
14020
14020
  return "";
14021
14021
  }
@@ -14037,14 +14037,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14037
14037
  /** Update memory scores based on task outcome. Called after task completion.
14038
14038
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
14039
14039
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
14040
- const { readFileSync: readFileSync40, writeFileSync: writeFileSync25, existsSync: existsSync52, mkdirSync: mkdirSync26 } = __require("node:fs");
14040
+ const { readFileSync: readFileSync41, writeFileSync: writeFileSync26, existsSync: existsSync53, mkdirSync: mkdirSync27 } = __require("node:fs");
14041
14041
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14042
14042
  const storeFile = join23(metaDir, "store.json");
14043
- if (!existsSync52(storeFile))
14043
+ if (!existsSync53(storeFile))
14044
14044
  return;
14045
14045
  let store = [];
14046
14046
  try {
14047
- store = JSON.parse(readFileSync40(storeFile, "utf8"));
14047
+ store = JSON.parse(readFileSync41(storeFile, "utf8"));
14048
14048
  } catch {
14049
14049
  return;
14050
14050
  }
@@ -14068,8 +14068,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14068
14068
  updated = true;
14069
14069
  }
14070
14070
  if (updated) {
14071
- mkdirSync26(metaDir, { recursive: true });
14072
- writeFileSync25(storeFile, JSON.stringify(store, null, 2));
14071
+ mkdirSync27(metaDir, { recursive: true });
14072
+ writeFileSync26(storeFile, JSON.stringify(store, null, 2));
14073
14073
  }
14074
14074
  }
14075
14075
  // ── Storage ──────────────────────────────────────────────────────────
@@ -14491,13 +14491,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14491
14491
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
14492
14492
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
14493
14493
  getRelevantStrategiesSync(k = 3, taskType) {
14494
- const { readFileSync: readFileSync40, existsSync: existsSync52 } = __require("node:fs");
14494
+ const { readFileSync: readFileSync41, existsSync: existsSync53 } = __require("node:fs");
14495
14495
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14496
- if (!existsSync52(archiveFile))
14496
+ if (!existsSync53(archiveFile))
14497
14497
  return "";
14498
14498
  let variants = [];
14499
14499
  try {
14500
- variants = JSON.parse(readFileSync40(archiveFile, "utf8"));
14500
+ variants = JSON.parse(readFileSync41(archiveFile, "utf8"));
14501
14501
  } catch {
14502
14502
  return "";
14503
14503
  }
@@ -14515,13 +14515,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14515
14515
  }
14516
14516
  /** Archive a strategy variant synchronously (for task completion path) */
14517
14517
  archiveVariantSync(strategy, outcome, tags = []) {
14518
- const { readFileSync: readFileSync40, writeFileSync: writeFileSync25, existsSync: existsSync52, mkdirSync: mkdirSync26 } = __require("node:fs");
14518
+ const { readFileSync: readFileSync41, writeFileSync: writeFileSync26, existsSync: existsSync53, mkdirSync: mkdirSync27 } = __require("node:fs");
14519
14519
  const dir = join25(this.cwd, ".oa", "arche");
14520
14520
  const archiveFile = join25(dir, "variants.json");
14521
14521
  let variants = [];
14522
14522
  try {
14523
- if (existsSync52(archiveFile))
14524
- variants = JSON.parse(readFileSync40(archiveFile, "utf8"));
14523
+ if (existsSync53(archiveFile))
14524
+ variants = JSON.parse(readFileSync41(archiveFile, "utf8"));
14525
14525
  } catch {
14526
14526
  }
14527
14527
  variants.push({
@@ -14536,8 +14536,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14536
14536
  });
14537
14537
  if (variants.length > 50)
14538
14538
  variants = variants.slice(-50);
14539
- mkdirSync26(dir, { recursive: true });
14540
- writeFileSync25(archiveFile, JSON.stringify(variants, null, 2));
14539
+ mkdirSync27(dir, { recursive: true });
14540
+ writeFileSync26(archiveFile, JSON.stringify(variants, null, 2));
14541
14541
  }
14542
14542
  async saveArchive(variants) {
14543
14543
  const dir = join25(this.cwd, ".oa", "arche");
@@ -26895,10 +26895,10 @@ ${marker}` : marker);
26895
26895
  if (!this._workingDirectory)
26896
26896
  return;
26897
26897
  try {
26898
- const { mkdirSync: mkdirSync26, writeFileSync: writeFileSync25 } = __require("node:fs");
26899
- const { join: join72 } = __require("node:path");
26900
- const sessionDir = join72(this._workingDirectory, ".oa", "session", this._sessionId);
26901
- mkdirSync26(sessionDir, { recursive: true });
26898
+ const { mkdirSync: mkdirSync27, writeFileSync: writeFileSync26 } = __require("node:fs");
26899
+ const { join: join73 } = __require("node:path");
26900
+ const sessionDir = join73(this._workingDirectory, ".oa", "session", this._sessionId);
26901
+ mkdirSync27(sessionDir, { recursive: true });
26902
26902
  const checkpoint = {
26903
26903
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26904
26904
  sessionId: this._sessionId,
@@ -26910,7 +26910,7 @@ ${marker}` : marker);
26910
26910
  memexEntryCount: this._memexArchive.size,
26911
26911
  fileRegistrySize: this._fileRegistry.size
26912
26912
  };
26913
- writeFileSync25(join72(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
26913
+ writeFileSync26(join73(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
26914
26914
  } catch {
26915
26915
  }
26916
26916
  }
@@ -34617,6 +34617,10 @@ var init_render = __esm({
34617
34617
  ["/nexus restart --clean", "Restart + clear metering data for fresh stats"],
34618
34618
  ["/nexus disconnect", "Kill daemon without reconnecting"],
34619
34619
  ["/nexus wallet", "Show wallet address and x402 payment status"],
34620
+ ["/sponsor", "Sponsor inference \u2014 onboarding wizard or dashboard"],
34621
+ ["/sponsor status", "Show sponsor dashboard with usage metrics"],
34622
+ ["/sponsor pause", "Pause active sponsorship"],
34623
+ ["/sponsor remove", "Remove sponsorship entirely"],
34620
34624
  ["/expose <backend>", "Expose local inference via libp2p (default)"],
34621
34625
  ["/expose <backend> --tunnel", "Expose via cloudflared tunnel"],
34622
34626
  ["/expose passthrough", "Forward configured /endpoint through libp2p P2P"],
@@ -35573,6 +35577,9 @@ var init_expose = __esm({
35573
35577
  /** Periodic PID watchdog for reconnect mode (no ChildProcess close event) */
35574
35578
  _pidWatchdog = null;
35575
35579
  _tunnelUrl = null;
35580
+ /** Debounce tracking for tunnel restarts */
35581
+ _lastRestartAttempt = 0;
35582
+ _consecutiveFailures = 0;
35576
35583
  _authKey;
35577
35584
  _targetUrl;
35578
35585
  _kind;
@@ -35634,16 +35641,19 @@ var init_expose = __esm({
35634
35641
  this.server.on("error", reject);
35635
35642
  });
35636
35643
  let lastStartErr;
35644
+ this._consecutiveFailures = 0;
35637
35645
  for (let attempt = 0; attempt < 3; attempt++) {
35638
35646
  try {
35647
+ this._lastRestartAttempt = Date.now();
35639
35648
  this._tunnelUrl = await this.startCloudflared(port);
35649
+ this._consecutiveFailures = 0;
35640
35650
  break;
35641
35651
  } catch (err) {
35642
35652
  lastStartErr = err instanceof Error ? err : new Error(String(err));
35643
- const is429 = lastStartErr.message.includes("429") || lastStartErr.message.includes("Too Many Requests");
35644
- if (is429 && attempt < 2) {
35645
- const delaySec = (attempt + 1) * 15;
35646
- this.options.onInfo?.(`Cloudflare rate limited \u2014 retrying in ${delaySec}s (attempt ${attempt + 2}/3)...`);
35653
+ this._consecutiveFailures++;
35654
+ if (attempt < 2) {
35655
+ const delaySec = Math.min(15 * Math.pow(2, attempt), 60);
35656
+ this.options.onInfo?.(`Tunnel start failed \u2014 retrying in ${delaySec}s (attempt ${attempt + 2}/3)...`);
35647
35657
  await new Promise((r) => setTimeout(r, delaySec * 1e3));
35648
35658
  continue;
35649
35659
  }
@@ -36052,9 +36062,19 @@ var init_expose = __esm({
36052
36062
  startCloudflared(port) {
36053
36063
  this._proxyPort = port;
36054
36064
  return new Promise((resolve35, reject) => {
36065
+ const TUNNEL_TIMEOUT_MS = 6e4;
36055
36066
  const timeout = setTimeout(() => {
36056
- reject(new Error("Cloudflared tunnel start timeout (30s)"));
36057
- }, 3e4);
36067
+ reject(new Error("Cloudflared tunnel start timeout (60s). Slow network? Try again."));
36068
+ }, TUNNEL_TIMEOUT_MS);
36069
+ let elapsed = 0;
36070
+ const progressInterval = setInterval(() => {
36071
+ elapsed += 5;
36072
+ this.options.onInfo?.(`Starting cloudflared tunnel... (${elapsed}s)`);
36073
+ }, 5e3);
36074
+ const cleanTimers = () => {
36075
+ clearTimeout(timeout);
36076
+ clearInterval(progressInterval);
36077
+ };
36058
36078
  this.cloudflaredProcess = spawn18("cloudflared", [
36059
36079
  "tunnel",
36060
36080
  "--url",
@@ -36074,9 +36094,14 @@ var init_expose = __esm({
36074
36094
  if (stderrOutput.length > 4096)
36075
36095
  stderrOutput = stderrOutput.slice(-4096);
36076
36096
  const urlMatch = text.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
36097
+ const statusMatch = text.match(/INF\s+(.*)/);
36098
+ if (statusMatch && !urlFound) {
36099
+ this.options.onInfo?.(`cloudflared: ${statusMatch[1].slice(0, 80)}`);
36100
+ }
36077
36101
  if (urlMatch && !urlFound) {
36078
36102
  urlFound = true;
36079
- clearTimeout(timeout);
36103
+ cleanTimers();
36104
+ this._consecutiveFailures = 0;
36080
36105
  this.cloudflaredProcess?.unref();
36081
36106
  this.cloudflaredProcess?.stdout?.destroy();
36082
36107
  this.cloudflaredProcess?.stderr?.destroy();
@@ -36086,59 +36111,80 @@ var init_expose = __esm({
36086
36111
  this.cloudflaredProcess.stdout?.on("data", handleOutput);
36087
36112
  this.cloudflaredProcess.stderr?.on("data", handleOutput);
36088
36113
  this.cloudflaredProcess.on("error", (err) => {
36089
- clearTimeout(timeout);
36090
- reject(new Error(`Failed to start cloudflared: ${err.message}`));
36114
+ cleanTimers();
36115
+ const msg = err.message;
36116
+ if (msg.includes("ENOENT")) {
36117
+ reject(new Error("cloudflared not installed. Install: brew install cloudflared (macOS) or download from https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/"));
36118
+ } else {
36119
+ reject(new Error(`Failed to start cloudflared: ${msg}`));
36120
+ }
36091
36121
  });
36092
36122
  this.cloudflaredProcess.on("close", (code) => {
36093
36123
  if (!urlFound) {
36094
- clearTimeout(timeout);
36124
+ cleanTimers();
36095
36125
  const hint = stderrOutput.trim().split("\n").slice(-3).join(" | ");
36096
- reject(new Error(`Cloudflared exited with code ${code}. ${hint ? "Output: " + hint : ""}`));
36126
+ if (hint.includes("address already in use")) {
36127
+ reject(new Error(`Port ${port} already in use. Another expose gateway may be running. Try: /expose stop first.`));
36128
+ } else if (hint.includes("429") || hint.includes("Too Many")) {
36129
+ reject(new Error(`Cloudflare rate limited (429). Wait 60s or use /expose libp2p instead.`));
36130
+ } else {
36131
+ reject(new Error(`Cloudflared exited with code ${code}. ${hint ? "Output: " + hint : ""}`));
36132
+ }
36097
36133
  }
36098
36134
  if (this._stats.status === "active") {
36099
- this.options.onInfo?.("Cloudflared tunnel died \u2014 restarting...");
36100
36135
  this._stats.status = "error";
36101
36136
  this.emitStats();
36102
- this.restartCloudflared();
36137
+ this.debouncedRestart();
36103
36138
  }
36104
36139
  });
36105
36140
  });
36106
36141
  }
36107
- /** Auto-restart cloudflared after unexpected exit (new URL assigned) */
36108
- async restartCloudflared() {
36142
+ /**
36143
+ * Debounced auto-restart: ensures minimum 10s between attempts,
36144
+ * exponential cooldown on consecutive failures, stops after 3 failures
36145
+ * and waits for manual `/expose tunnel` retry.
36146
+ */
36147
+ async debouncedRestart() {
36109
36148
  if (!this.server || this._proxyPort === 0)
36110
36149
  return;
36111
- for (let attempt = 0; attempt < 3; attempt++) {
36112
- try {
36113
- this._tunnelUrl = await this.startCloudflared(this._proxyPort);
36114
- this._stats.status = "active";
36115
- this.emitStats();
36116
- this.options.onInfo?.(`Tunnel restarted with new URL \u2014 share with consumers:
36150
+ this._consecutiveFailures++;
36151
+ if (this._consecutiveFailures >= 3) {
36152
+ this._stats.status = "standby";
36153
+ this.emitStats();
36154
+ this.options.onError?.(`Tunnel failed to start after ${this._consecutiveFailures} attempts.
36155
+ Type /expose tunnel to retry manually, or /expose libp2p as alternative.`);
36156
+ return;
36157
+ }
36158
+ const cooldownSec = Math.min(10 * Math.pow(2, this._consecutiveFailures - 1), 300);
36159
+ const sinceLast = (Date.now() - this._lastRestartAttempt) / 1e3;
36160
+ const waitSec = Math.max(cooldownSec - sinceLast, 0);
36161
+ if (waitSec > 0) {
36162
+ this.options.onInfo?.(`Tunnel died \u2014 will retry in ${Math.ceil(waitSec)}s (attempt ${this._consecutiveFailures + 1}/3)...`);
36163
+ await new Promise((r) => setTimeout(r, waitSec * 1e3));
36164
+ }
36165
+ this._lastRestartAttempt = Date.now();
36166
+ try {
36167
+ this._tunnelUrl = await this.startCloudflared(this._proxyPort);
36168
+ this._stats.status = "active";
36169
+ this._consecutiveFailures = 0;
36170
+ this.emitStats();
36171
+ this.options.onInfo?.(`Tunnel restarted with new URL \u2014 share with consumers:
36117
36172
  ${this.formatConnectionInfo()}`);
36118
- if (this._stateDir) {
36119
- writeExposeState(this._stateDir, {
36120
- pid: this._cloudflaredPid,
36121
- tunnelUrl: this._tunnelUrl,
36122
- authKey: this._authKey,
36123
- proxyPort: this._proxyPort,
36124
- targetUrl: this._targetUrl,
36125
- kind: this._kind,
36126
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
36127
- });
36128
- }
36129
- return;
36130
- } catch (err) {
36131
- const msg = err instanceof Error ? err.message : String(err);
36132
- const is429 = msg.includes("429") || msg.includes("Too Many Requests");
36133
- if (is429 && attempt < 2) {
36134
- const delaySec = (attempt + 1) * 15;
36135
- this.options.onInfo?.(`Cloudflare rate limited \u2014 retrying in ${delaySec}s...`);
36136
- await new Promise((r) => setTimeout(r, delaySec * 1e3));
36137
- continue;
36138
- }
36139
- this.options.onError?.(`Tunnel restart failed: ${msg}`);
36140
- return;
36173
+ if (this._stateDir) {
36174
+ writeExposeState(this._stateDir, {
36175
+ pid: this._cloudflaredPid,
36176
+ tunnelUrl: this._tunnelUrl,
36177
+ authKey: this._authKey,
36178
+ proxyPort: this._proxyPort,
36179
+ targetUrl: this._targetUrl,
36180
+ kind: this._kind,
36181
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
36182
+ });
36141
36183
  }
36184
+ } catch (err) {
36185
+ const msg = err instanceof Error ? err.message : String(err);
36186
+ this.options.onError?.(`Tunnel restart failed (attempt ${this._consecutiveFailures}/3): ${msg}`);
36187
+ this.debouncedRestart();
36142
36188
  }
36143
36189
  }
36144
36190
  /**
@@ -36155,7 +36201,7 @@ ${this.formatConnectionInfo()}`);
36155
36201
  this.options.onInfo?.("Cloudflared tunnel died (detected by watchdog) \u2014 restarting...");
36156
36202
  this._stats.status = "error";
36157
36203
  this.emitStats();
36158
- this.restartCloudflared();
36204
+ this.debouncedRestart();
36159
36205
  }
36160
36206
  }
36161
36207
  }, 1e4);
@@ -38138,26 +38184,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
38138
38184
  async function fetchPeerModels(peerId, authKey) {
38139
38185
  try {
38140
38186
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
38141
- const { existsSync: existsSync52, readFileSync: readFileSync40 } = await import("node:fs");
38142
- const { join: join72 } = await import("node:path");
38187
+ const { existsSync: existsSync53, readFileSync: readFileSync41 } = await import("node:fs");
38188
+ const { join: join73 } = await import("node:path");
38143
38189
  const cwd4 = process.cwd();
38144
38190
  const nexusTool = new NexusTool2(cwd4);
38145
38191
  const nexusDir = nexusTool.getNexusDir();
38146
38192
  let isLocalPeer = false;
38147
38193
  try {
38148
- const statusPath = join72(nexusDir, "status.json");
38149
- if (existsSync52(statusPath)) {
38150
- const status = JSON.parse(readFileSync40(statusPath, "utf8"));
38194
+ const statusPath = join73(nexusDir, "status.json");
38195
+ if (existsSync53(statusPath)) {
38196
+ const status = JSON.parse(readFileSync41(statusPath, "utf8"));
38151
38197
  if (status.peerId === peerId)
38152
38198
  isLocalPeer = true;
38153
38199
  }
38154
38200
  } catch {
38155
38201
  }
38156
38202
  if (isLocalPeer) {
38157
- const pricingPath = join72(nexusDir, "pricing.json");
38158
- if (existsSync52(pricingPath)) {
38203
+ const pricingPath = join73(nexusDir, "pricing.json");
38204
+ if (existsSync53(pricingPath)) {
38159
38205
  try {
38160
- const pricing = JSON.parse(readFileSync40(pricingPath, "utf8"));
38206
+ const pricing = JSON.parse(readFileSync41(pricingPath, "utf8"));
38161
38207
  const localModels = (pricing.models || []).map((m) => ({
38162
38208
  name: m.model || "unknown",
38163
38209
  size: m.parameterSize || "",
@@ -38171,10 +38217,10 @@ async function fetchPeerModels(peerId, authKey) {
38171
38217
  }
38172
38218
  }
38173
38219
  }
38174
- const cachePath = join72(nexusDir, "peer-models-cache.json");
38175
- if (existsSync52(cachePath)) {
38220
+ const cachePath = join73(nexusDir, "peer-models-cache.json");
38221
+ if (existsSync53(cachePath)) {
38176
38222
  try {
38177
- const cache4 = JSON.parse(readFileSync40(cachePath, "utf8"));
38223
+ const cache4 = JSON.parse(readFileSync41(cachePath, "utf8"));
38178
38224
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
38179
38225
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
38180
38226
  if (age < 5 * 60 * 1e3) {
@@ -38289,10 +38335,10 @@ async function fetchPeerModels(peerId, authKey) {
38289
38335
  } catch {
38290
38336
  }
38291
38337
  if (isLocalPeer) {
38292
- const pricingPath = join72(nexusDir, "pricing.json");
38293
- if (existsSync52(pricingPath)) {
38338
+ const pricingPath = join73(nexusDir, "pricing.json");
38339
+ if (existsSync53(pricingPath)) {
38294
38340
  try {
38295
- const pricing = JSON.parse(readFileSync40(pricingPath, "utf8"));
38341
+ const pricing = JSON.parse(readFileSync41(pricingPath, "utf8"));
38296
38342
  return (pricing.models || []).map((m) => ({
38297
38343
  name: m.model || "unknown",
38298
38344
  size: m.parameterSize || "",
@@ -42325,6 +42371,471 @@ var init_neovim_mode = __esm({
42325
42371
  }
42326
42372
  });
42327
42373
 
42374
+ // packages/cli/dist/tui/sponsor-wizard.js
42375
+ var sponsor_wizard_exports = {};
42376
+ __export(sponsor_wizard_exports, {
42377
+ loadSponsorConfig: () => loadSponsorConfig,
42378
+ runSponsorWizard: () => runSponsorWizard,
42379
+ saveSponsorConfig: () => saveSponsorConfig,
42380
+ showSponsorDashboard: () => showSponsorDashboard
42381
+ });
42382
+ import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync16 } from "node:fs";
42383
+ import { join as join56 } from "node:path";
42384
+ function sponsorDir(projectDir) {
42385
+ return join56(projectDir, ".oa", "sponsor");
42386
+ }
42387
+ function configPath(projectDir) {
42388
+ return join56(sponsorDir(projectDir), "config.json");
42389
+ }
42390
+ function loadSponsorConfig(projectDir) {
42391
+ const p = configPath(projectDir);
42392
+ if (!existsSync40(p))
42393
+ return null;
42394
+ try {
42395
+ return JSON.parse(readFileSync29(p, "utf8"));
42396
+ } catch {
42397
+ return null;
42398
+ }
42399
+ }
42400
+ function saveSponsorConfig(projectDir, config) {
42401
+ const dir = sponsorDir(projectDir);
42402
+ mkdirSync16(dir, { recursive: true });
42403
+ config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
42404
+ writeFileSync17(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
42405
+ }
42406
+ function defaultConfig() {
42407
+ return {
42408
+ endpoints: [],
42409
+ banner: { preset: "wave" },
42410
+ header: {
42411
+ messageEnabled: false,
42412
+ message: "",
42413
+ linkEnabled: false,
42414
+ linkUrl: "",
42415
+ linkText: ""
42416
+ },
42417
+ transport: { cloudflared: true, libp2p: false },
42418
+ rateLimits: {
42419
+ maxRequestsPerMinute: 60,
42420
+ maxTokensPerDay: 1e5,
42421
+ maxConcurrent: 5,
42422
+ allowedModels: "all"
42423
+ },
42424
+ status: "inactive",
42425
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
42426
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
42427
+ };
42428
+ }
42429
+ async function discoverEndpoints(ollamaUrl) {
42430
+ const endpoints = [];
42431
+ try {
42432
+ const resp = await fetch(`${ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(5e3) });
42433
+ if (resp.ok) {
42434
+ const data = await resp.json();
42435
+ const models = (data.models || []).map((m) => m.name);
42436
+ endpoints.push({
42437
+ kind: "ollama",
42438
+ url: ollamaUrl,
42439
+ models,
42440
+ label: `Local Ollama (${new URL(ollamaUrl).host})`,
42441
+ enabled: true
42442
+ });
42443
+ }
42444
+ } catch {
42445
+ }
42446
+ return endpoints;
42447
+ }
42448
+ async function stepEndpoints(config, ollamaUrl, rl, availableRows) {
42449
+ const discovered = await discoverEndpoints(ollamaUrl);
42450
+ for (const disc of discovered) {
42451
+ const existing = config.endpoints.find((e) => e.url === disc.url);
42452
+ if (!existing) {
42453
+ config.endpoints.push(disc);
42454
+ } else {
42455
+ existing.models = disc.models;
42456
+ }
42457
+ }
42458
+ const items = [
42459
+ { key: "hdr", label: "Select Endpoints to Sponsor", isToggleable: false }
42460
+ ];
42461
+ for (const ep of config.endpoints) {
42462
+ const modelList = ep.models.length > 0 ? ep.models.slice(0, 3).join(", ") + (ep.models.length > 3 ? ` +${ep.models.length - 3} more` : "") : "all models";
42463
+ items.push({
42464
+ key: ep.url,
42465
+ label: `${ep.enabled ? "[x]" : "[ ]"} ${ep.label}`,
42466
+ detail: `Models: ${modelList}`,
42467
+ endpoint: ep,
42468
+ isToggleable: true
42469
+ });
42470
+ }
42471
+ items.push({
42472
+ key: "add_custom",
42473
+ label: " + Add custom endpoint URL...",
42474
+ isToggleable: false
42475
+ });
42476
+ items.push({ key: "sep", label: "", isToggleable: false });
42477
+ items.push({
42478
+ key: "next",
42479
+ label: selectColors.green(" Next Step \u2192"),
42480
+ isToggleable: false
42481
+ });
42482
+ const result = await tuiSelect({
42483
+ items,
42484
+ title: "Step 1/5 \u2014 Endpoint Selection",
42485
+ rl,
42486
+ skipKeys: ["hdr", "sep"],
42487
+ availableRows,
42488
+ onAction: (item, action) => {
42489
+ if (action === "space" && item.isToggleable && item.endpoint) {
42490
+ item.endpoint.enabled = !item.endpoint.enabled;
42491
+ item.label = `${item.endpoint.enabled ? "[x]" : "[ ]"} ${item.endpoint.label}`;
42492
+ return true;
42493
+ }
42494
+ return false;
42495
+ },
42496
+ renderRow: (item, focused, _isActive) => {
42497
+ const prefix = focused ? selectColors.orange("\u276F ") : " ";
42498
+ if (item.key === "hdr") {
42499
+ return selectColors.bold(item.label);
42500
+ }
42501
+ if (item.detail) {
42502
+ return `${prefix}${item.label}
42503
+ ${selectColors.dim(item.detail)}`;
42504
+ }
42505
+ return `${prefix}${item.label}`;
42506
+ }
42507
+ });
42508
+ if (!result.confirmed)
42509
+ return false;
42510
+ if (result.key === "next") {
42511
+ const anyEnabled = config.endpoints.some((e) => e.enabled);
42512
+ if (!anyEnabled) {
42513
+ renderWarning("Select at least one endpoint before continuing.");
42514
+ return stepEndpoints(config, ollamaUrl, rl, availableRows);
42515
+ }
42516
+ return true;
42517
+ }
42518
+ if (result.key && result.key !== "add_custom") {
42519
+ const ep = config.endpoints.find((e) => e.url === result.key);
42520
+ if (ep) {
42521
+ ep.enabled = !ep.enabled;
42522
+ return stepEndpoints(config, ollamaUrl, rl, availableRows);
42523
+ }
42524
+ }
42525
+ if (result.key === "add_custom") {
42526
+ renderInfo("Custom endpoint support coming soon. Use /endpoint to configure external APIs.");
42527
+ return stepEndpoints(config, ollamaUrl, rl, availableRows);
42528
+ }
42529
+ return false;
42530
+ }
42531
+ async function stepBanner(config, rl, availableRows) {
42532
+ const items = [
42533
+ { key: "hdr", label: "Select Banner Animation" }
42534
+ ];
42535
+ for (const preset of ANIM_PRESETS) {
42536
+ items.push({
42537
+ key: preset.id,
42538
+ label: `${config.banner.preset === preset.id ? "(\u25CF)" : "( )"} ${preset.name}`,
42539
+ detail: preset.desc
42540
+ });
42541
+ }
42542
+ items.push({ key: "sep", label: "" });
42543
+ items.push({ key: "next", label: selectColors.green(" Next Step \u2192") });
42544
+ const result = await tuiSelect({
42545
+ items,
42546
+ title: "Step 2/5 \u2014 Banner Animation",
42547
+ rl,
42548
+ skipKeys: ["hdr", "sep"],
42549
+ availableRows,
42550
+ onAction: (item, action) => {
42551
+ if (action === "space" && ANIM_PRESETS.some((p) => p.id === item.key)) {
42552
+ config.banner.preset = item.key;
42553
+ for (const it of items) {
42554
+ const p = ANIM_PRESETS.find((pr) => pr.id === it.key);
42555
+ if (p) {
42556
+ it.label = `${config.banner.preset === p.id ? "(\u25CF)" : "( )"} ${p.name}`;
42557
+ }
42558
+ }
42559
+ return true;
42560
+ }
42561
+ return false;
42562
+ }
42563
+ });
42564
+ if (!result.confirmed)
42565
+ return false;
42566
+ if (result.key === "next")
42567
+ return true;
42568
+ if (ANIM_PRESETS.some((p) => p.id === result.key)) {
42569
+ config.banner.preset = result.key;
42570
+ return true;
42571
+ }
42572
+ return false;
42573
+ }
42574
+ async function stepHeader(config, rl, availableRows) {
42575
+ const items = [
42576
+ { key: "hdr", label: "Header Content" },
42577
+ {
42578
+ key: "message_toggle",
42579
+ label: `${config.header.messageEnabled ? "[x]" : "[ ]"} Header Message`,
42580
+ detail: config.header.message || "(none set)"
42581
+ },
42582
+ {
42583
+ key: "link_toggle",
42584
+ label: `${config.header.linkEnabled ? "[x]" : "[ ]"} Link`,
42585
+ detail: config.header.linkUrl ? `${config.header.linkUrl} [${config.header.linkText || "link"}]` : "(none set)"
42586
+ },
42587
+ { key: "sep", label: "" },
42588
+ { key: "next", label: selectColors.green(" Next Step \u2192") }
42589
+ ];
42590
+ const result = await tuiSelect({
42591
+ items,
42592
+ title: "Step 3/5 \u2014 Header Text & Links",
42593
+ rl,
42594
+ skipKeys: ["hdr", "sep"],
42595
+ availableRows,
42596
+ onAction: (item, action) => {
42597
+ if (action === "space") {
42598
+ if (item.key === "message_toggle") {
42599
+ config.header.messageEnabled = !config.header.messageEnabled;
42600
+ item.label = `${config.header.messageEnabled ? "[x]" : "[ ]"} Header Message`;
42601
+ return true;
42602
+ }
42603
+ if (item.key === "link_toggle") {
42604
+ config.header.linkEnabled = !config.header.linkEnabled;
42605
+ item.label = `${config.header.linkEnabled ? "[x]" : "[ ]"} Link`;
42606
+ return true;
42607
+ }
42608
+ }
42609
+ return false;
42610
+ }
42611
+ });
42612
+ if (!result.confirmed)
42613
+ return false;
42614
+ if (result.key === "next")
42615
+ return true;
42616
+ if (result.key === "message_toggle") {
42617
+ config.header.messageEnabled = true;
42618
+ const msg = await promptLine(rl, "Header message: ");
42619
+ if (msg)
42620
+ config.header.message = msg.slice(0, 80);
42621
+ return stepHeader(config, rl, availableRows);
42622
+ }
42623
+ if (result.key === "link_toggle") {
42624
+ config.header.linkEnabled = true;
42625
+ const url = await promptLine(rl, "Link URL: ");
42626
+ if (url) {
42627
+ config.header.linkUrl = url;
42628
+ const text = await promptLine(rl, "Link text: ");
42629
+ if (text)
42630
+ config.header.linkText = text;
42631
+ }
42632
+ return stepHeader(config, rl, availableRows);
42633
+ }
42634
+ return false;
42635
+ }
42636
+ async function stepTransport(config, rl, availableRows) {
42637
+ const items = [
42638
+ { key: "hdr_transport", label: "Network Transport" },
42639
+ {
42640
+ key: "cf_toggle",
42641
+ label: `${config.transport.cloudflared ? "[x]" : "[ ]"} Cloudflared Tunnel (HTTPS)`,
42642
+ detail: "Public URL via trycloudflare.com"
42643
+ },
42644
+ {
42645
+ key: "p2p_toggle",
42646
+ label: `${config.transport.libp2p ? "[x]" : "[ ]"} libp2p P2P Mesh`,
42647
+ detail: "Decentralized, no central relay"
42648
+ },
42649
+ { key: "hdr_limits", label: "Rate Limits" },
42650
+ {
42651
+ key: "rpm",
42652
+ label: ` Max requests/min: ${config.rateLimits.maxRequestsPerMinute}`
42653
+ },
42654
+ {
42655
+ key: "tpd",
42656
+ label: ` Max tokens/day: ${config.rateLimits.maxTokensPerDay.toLocaleString()}`
42657
+ },
42658
+ {
42659
+ key: "conc",
42660
+ label: ` Max concurrent: ${config.rateLimits.maxConcurrent}`
42661
+ },
42662
+ { key: "sep", label: "" },
42663
+ { key: "next", label: selectColors.green(" Next Step \u2192") }
42664
+ ];
42665
+ const result = await tuiSelect({
42666
+ items,
42667
+ title: "Step 4/5 \u2014 Transport & Rate Limits",
42668
+ rl,
42669
+ skipKeys: ["hdr_transport", "hdr_limits", "sep"],
42670
+ availableRows,
42671
+ onAction: (item, action) => {
42672
+ if (action === "space") {
42673
+ if (item.key === "cf_toggle") {
42674
+ config.transport.cloudflared = !config.transport.cloudflared;
42675
+ item.label = `${config.transport.cloudflared ? "[x]" : "[ ]"} Cloudflared Tunnel (HTTPS)`;
42676
+ return true;
42677
+ }
42678
+ if (item.key === "p2p_toggle") {
42679
+ config.transport.libp2p = !config.transport.libp2p;
42680
+ item.label = `${config.transport.libp2p ? "[x]" : "[ ]"} libp2p P2P Mesh`;
42681
+ return true;
42682
+ }
42683
+ }
42684
+ return false;
42685
+ }
42686
+ });
42687
+ if (!result.confirmed)
42688
+ return false;
42689
+ if (result.key === "next") {
42690
+ if (!config.transport.cloudflared && !config.transport.libp2p) {
42691
+ renderWarning("At least one transport must be enabled.");
42692
+ return stepTransport(config, rl, availableRows);
42693
+ }
42694
+ return true;
42695
+ }
42696
+ if (result.key === "rpm") {
42697
+ const val = await promptLine(rl, "Max requests per minute: ");
42698
+ const n = parseInt(val, 10);
42699
+ if (!isNaN(n) && n > 0)
42700
+ config.rateLimits.maxRequestsPerMinute = n;
42701
+ return stepTransport(config, rl, availableRows);
42702
+ }
42703
+ if (result.key === "tpd") {
42704
+ const val = await promptLine(rl, "Max tokens per day: ");
42705
+ const n = parseInt(val, 10);
42706
+ if (!isNaN(n) && n > 0)
42707
+ config.rateLimits.maxTokensPerDay = n;
42708
+ return stepTransport(config, rl, availableRows);
42709
+ }
42710
+ if (result.key === "conc") {
42711
+ const val = await promptLine(rl, "Max concurrent requests: ");
42712
+ const n = parseInt(val, 10);
42713
+ if (!isNaN(n) && n > 0)
42714
+ config.rateLimits.maxConcurrent = n;
42715
+ return stepTransport(config, rl, availableRows);
42716
+ }
42717
+ return false;
42718
+ }
42719
+ async function stepReview(config, rl, availableRows) {
42720
+ const enabledEps = config.endpoints.filter((e) => e.enabled);
42721
+ const epList = enabledEps.map((e) => e.label).join(", ") || "none";
42722
+ const transports = [];
42723
+ if (config.transport.cloudflared)
42724
+ transports.push("Cloudflared Tunnel");
42725
+ if (config.transport.libp2p)
42726
+ transports.push("libp2p P2P");
42727
+ const items = [
42728
+ { key: "hdr", label: "Review Sponsorship Configuration" },
42729
+ { key: "info_ep", label: ` Endpoints: ${epList}` },
42730
+ { key: "info_anim", label: ` Banner: ${config.banner.preset}` },
42731
+ { key: "info_msg", label: ` Message: ${config.header.messageEnabled ? config.header.message || "(empty)" : "(disabled)"}` },
42732
+ { key: "info_link", label: ` Link: ${config.header.linkEnabled ? `${config.header.linkUrl} [${config.header.linkText}]` : "(disabled)"}` },
42733
+ { key: "info_transport", label: ` Transport: ${transports.join(" + ")}` },
42734
+ { key: "info_limits", label: ` Limits: ${config.rateLimits.maxRequestsPerMinute} req/min, ${config.rateLimits.maxTokensPerDay.toLocaleString()} tokens/day` },
42735
+ { key: "sep", label: "" },
42736
+ { key: "go_live", label: selectColors.green(" \u2726 Go Live & Sponsor Inference ") },
42737
+ { key: "cancel", label: selectColors.dim(" Cancel") }
42738
+ ];
42739
+ const result = await tuiSelect({
42740
+ items,
42741
+ title: "Step 5/5 \u2014 Review & Go Live",
42742
+ rl,
42743
+ skipKeys: ["hdr", "sep", "info_ep", "info_anim", "info_msg", "info_link", "info_transport", "info_limits"],
42744
+ availableRows
42745
+ });
42746
+ if (!result.confirmed || result.key === "cancel")
42747
+ return false;
42748
+ return result.key === "go_live";
42749
+ }
42750
+ async function showSponsorDashboard(config, projectDir, rl, availableRows) {
42751
+ const isPaused = config.status === "paused";
42752
+ const enabledEps = config.endpoints.filter((e) => e.enabled);
42753
+ const items = [
42754
+ { key: "hdr", label: "Sponsor Dashboard" },
42755
+ { key: "info_status", label: ` Status: ${isPaused ? "\u25CF PAUSED" : "\u25CF ACTIVE"}` },
42756
+ { key: "info_ep", label: ` Endpoints: ${enabledEps.map((e) => e.label).join(", ")}` },
42757
+ { key: "info_transport", label: ` Transport: ${[config.transport.cloudflared ? "Cloudflared" : "", config.transport.libp2p ? "libp2p" : ""].filter(Boolean).join(" + ")}` },
42758
+ { key: "info_limits", label: ` Limits: ${config.rateLimits.maxRequestsPerMinute} req/min, ${config.rateLimits.maxTokensPerDay.toLocaleString()} tokens/day` },
42759
+ { key: "sep", label: "" },
42760
+ { key: "modify", label: " [Modify Settings]" },
42761
+ { key: isPaused ? "resume" : "pause", label: isPaused ? " [Resume Sponsorship]" : " [Pause Sponsorship]" },
42762
+ { key: "remove", label: selectColors.dim(" [Remove Sponsorship]") }
42763
+ ];
42764
+ const result = await tuiSelect({
42765
+ items,
42766
+ title: "Sponsor Dashboard",
42767
+ rl,
42768
+ skipKeys: ["hdr", "sep", "info_status", "info_ep", "info_transport", "info_limits"],
42769
+ availableRows
42770
+ });
42771
+ if (!result.confirmed)
42772
+ return "close";
42773
+ return result.key || "close";
42774
+ }
42775
+ async function runSponsorWizard(ctx) {
42776
+ let config = loadSponsorConfig(ctx.projectDir) || defaultConfig();
42777
+ renderInfo("Starting sponsor onboarding wizard...\n");
42778
+ if (!await stepEndpoints(config, ctx.ollamaUrl, ctx.rl, ctx.availableRows)) {
42779
+ renderInfo("Sponsor wizard cancelled.");
42780
+ return null;
42781
+ }
42782
+ saveSponsorConfig(ctx.projectDir, config);
42783
+ if (!await stepBanner(config, ctx.rl, ctx.availableRows)) {
42784
+ renderInfo("Sponsor wizard cancelled.");
42785
+ return null;
42786
+ }
42787
+ saveSponsorConfig(ctx.projectDir, config);
42788
+ if (!await stepHeader(config, ctx.rl, ctx.availableRows)) {
42789
+ renderInfo("Sponsor wizard cancelled.");
42790
+ return null;
42791
+ }
42792
+ saveSponsorConfig(ctx.projectDir, config);
42793
+ if (!await stepTransport(config, ctx.rl, ctx.availableRows)) {
42794
+ renderInfo("Sponsor wizard cancelled.");
42795
+ return null;
42796
+ }
42797
+ saveSponsorConfig(ctx.projectDir, config);
42798
+ if (!await stepReview(config, ctx.rl, ctx.availableRows)) {
42799
+ renderInfo("Sponsor wizard cancelled.");
42800
+ return null;
42801
+ }
42802
+ config.status = "active";
42803
+ saveSponsorConfig(ctx.projectDir, config);
42804
+ if (ctx.onGoLive) {
42805
+ await ctx.onGoLive(config);
42806
+ }
42807
+ renderInfo("\u2726 Sponsorship active!");
42808
+ renderInfo("Toggle: /sponsor status | Pause: /sponsor pause | Remove: /sponsor remove");
42809
+ return config;
42810
+ }
42811
+ function promptLine(rl, prompt) {
42812
+ return new Promise((resolve35) => {
42813
+ process.stdout.write(prompt);
42814
+ const handler = (line) => {
42815
+ rl.removeListener("line", handler);
42816
+ resolve35(line.trim());
42817
+ };
42818
+ rl.on("line", handler);
42819
+ });
42820
+ }
42821
+ var ANIM_PRESETS;
42822
+ var init_sponsor_wizard = __esm({
42823
+ "packages/cli/dist/tui/sponsor-wizard.js"() {
42824
+ "use strict";
42825
+ init_tui_select();
42826
+ init_render();
42827
+ ANIM_PRESETS = [
42828
+ { id: "wave", name: "Wave", desc: "Flowing wave pattern" },
42829
+ { id: "pulse", name: "Pulse", desc: "Pulsing dots" },
42830
+ { id: "matrix", name: "Matrix", desc: "Falling characters" },
42831
+ { id: "sparkle", name: "Sparkle", desc: "Random sparkle effect" },
42832
+ { id: "radar", name: "Radar", desc: "Rotating radar sweep" },
42833
+ { id: "circuit", name: "Circuit", desc: "Circuit board traces" },
42834
+ { id: "none", name: "No Animation", desc: "Static banner only" }
42835
+ ];
42836
+ }
42837
+ });
42838
+
42328
42839
  // packages/cli/dist/tui/voice.js
42329
42840
  var voice_exports = {};
42330
42841
  __export(voice_exports, {
@@ -42337,8 +42848,8 @@ __export(voice_exports, {
42337
42848
  registerCustomOnnxModel: () => registerCustomOnnxModel,
42338
42849
  resetNarrationContext: () => resetNarrationContext
42339
42850
  });
42340
- import { existsSync as existsSync40, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, readFileSync as readFileSync29, unlinkSync as unlinkSync9, readdirSync as readdirSync11, renameSync, statSync as statSync13 } from "node:fs";
42341
- import { join as join56, dirname as dirname18 } from "node:path";
42851
+ import { existsSync as existsSync41, mkdirSync as mkdirSync17, writeFileSync as writeFileSync18, readFileSync as readFileSync30, unlinkSync as unlinkSync9, readdirSync as readdirSync11, renameSync, statSync as statSync13 } from "node:fs";
42852
+ import { join as join57, dirname as dirname18 } from "node:path";
42342
42853
  import { homedir as homedir13, tmpdir as tmpdir9, platform as platform3 } from "node:os";
42343
42854
  import { execSync as execSync29, spawn as nodeSpawn } from "node:child_process";
42344
42855
  import { createRequire } from "node:module";
@@ -42363,40 +42874,40 @@ function listVoiceModels() {
42363
42874
  }));
42364
42875
  }
42365
42876
  function voiceDir() {
42366
- return join56(homedir13(), ".open-agents", "voice");
42877
+ return join57(homedir13(), ".open-agents", "voice");
42367
42878
  }
42368
42879
  function modelsDir() {
42369
- return join56(voiceDir(), "models");
42880
+ return join57(voiceDir(), "models");
42370
42881
  }
42371
42882
  function modelDir(id) {
42372
- return join56(modelsDir(), id);
42883
+ return join57(modelsDir(), id);
42373
42884
  }
42374
42885
  function modelOnnxPath(id) {
42375
- return join56(modelDir(id), "model.onnx");
42886
+ return join57(modelDir(id), "model.onnx");
42376
42887
  }
42377
42888
  function modelConfigPath(id) {
42378
- return join56(modelDir(id), "config.json");
42889
+ return join57(modelDir(id), "config.json");
42379
42890
  }
42380
42891
  function luxttsVenvDir() {
42381
- return join56(voiceDir(), "luxtts-venv");
42892
+ return join57(voiceDir(), "luxtts-venv");
42382
42893
  }
42383
42894
  function luxttsVenvPy() {
42384
- return platform3() === "win32" ? join56(luxttsVenvDir(), "Scripts", "python.exe") : join56(luxttsVenvDir(), "bin", "python3");
42895
+ return platform3() === "win32" ? join57(luxttsVenvDir(), "Scripts", "python.exe") : join57(luxttsVenvDir(), "bin", "python3");
42385
42896
  }
42386
42897
  function luxttsRepoDir() {
42387
- return join56(voiceDir(), "LuxTTS");
42898
+ return join57(voiceDir(), "LuxTTS");
42388
42899
  }
42389
42900
  function luxttsCloneRefsDir() {
42390
- return join56(voiceDir(), "clone-refs");
42901
+ return join57(voiceDir(), "clone-refs");
42391
42902
  }
42392
42903
  function luxttsInferScript() {
42393
- return join56(voiceDir(), "luxtts-infer.py");
42904
+ return join57(voiceDir(), "luxtts-infer.py");
42394
42905
  }
42395
42906
  function writeDetectTorchScript(targetPath) {
42396
- if (existsSync40(targetPath))
42907
+ if (existsSync41(targetPath))
42397
42908
  return;
42398
42909
  try {
42399
- mkdirSync16(dirname18(targetPath), { recursive: true });
42910
+ mkdirSync17(dirname18(targetPath), { recursive: true });
42400
42911
  } catch {
42401
42912
  }
42402
42913
  const script = `#!/usr/bin/env python3
@@ -42469,7 +42980,7 @@ def main():
42469
42980
  if __name__ == "__main__": main()
42470
42981
  `;
42471
42982
  try {
42472
- writeFileSync17(targetPath, script, { mode: 493 });
42983
+ writeFileSync18(targetPath, script, { mode: 493 });
42473
42984
  } catch {
42474
42985
  }
42475
42986
  }
@@ -43279,8 +43790,8 @@ var init_voice = __esm({
43279
43790
  const refsDir = luxttsCloneRefsDir();
43280
43791
  const targets = ["glados", "overwatch"];
43281
43792
  for (const modelId of targets) {
43282
- const refFile = join56(refsDir, `${modelId}-ref.wav`);
43283
- if (existsSync40(refFile))
43793
+ const refFile = join57(refsDir, `${modelId}-ref.wav`);
43794
+ if (existsSync41(refFile))
43284
43795
  continue;
43285
43796
  try {
43286
43797
  await this.generateCloneRef(modelId);
@@ -43359,24 +43870,24 @@ var init_voice = __esm({
43359
43870
  }
43360
43871
  p = p.replace(/\\ /g, " ");
43361
43872
  if (p.startsWith("~/") || p === "~") {
43362
- p = join56(homedir13(), p.slice(1));
43873
+ p = join57(homedir13(), p.slice(1));
43363
43874
  }
43364
- if (!existsSync40(p)) {
43875
+ if (!existsSync41(p)) {
43365
43876
  return `File not found: ${p}
43366
43877
  (original input: ${audioPath})`;
43367
43878
  }
43368
43879
  audioPath = p;
43369
43880
  const refsDir = luxttsCloneRefsDir();
43370
- if (!existsSync40(refsDir))
43371
- mkdirSync16(refsDir, { recursive: true });
43881
+ if (!existsSync41(refsDir))
43882
+ mkdirSync17(refsDir, { recursive: true });
43372
43883
  const ext = audioPath.split(".").pop() || "wav";
43373
43884
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
43374
43885
  const ts = Date.now().toString(36);
43375
43886
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
43376
- const destPath = join56(refsDir, destFilename);
43887
+ const destPath = join57(refsDir, destFilename);
43377
43888
  try {
43378
- const data = readFileSync29(audioPath);
43379
- writeFileSync17(destPath, data);
43889
+ const data = readFileSync30(audioPath);
43890
+ writeFileSync18(destPath, data);
43380
43891
  } catch (err) {
43381
43892
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
43382
43893
  }
@@ -43416,9 +43927,9 @@ var init_voice = __esm({
43416
43927
  return `Failed to synthesize reference audio from ${source.label}.`;
43417
43928
  }
43418
43929
  const refsDir = luxttsCloneRefsDir();
43419
- if (!existsSync40(refsDir))
43420
- mkdirSync16(refsDir, { recursive: true });
43421
- const destPath = join56(refsDir, `${sourceModelId}-ref.wav`);
43930
+ if (!existsSync41(refsDir))
43931
+ mkdirSync17(refsDir, { recursive: true });
43932
+ const destPath = join57(refsDir, `${sourceModelId}-ref.wav`);
43422
43933
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
43423
43934
  this.writeWav(audioData, sampleRate, destPath);
43424
43935
  this.luxttsCloneRef = destPath;
@@ -43434,23 +43945,23 @@ var init_voice = __esm({
43434
43945
  // -------------------------------------------------------------------------
43435
43946
  /** Metadata file for friendly names of clone refs */
43436
43947
  static cloneMetaFile() {
43437
- return join56(luxttsCloneRefsDir(), "meta.json");
43948
+ return join57(luxttsCloneRefsDir(), "meta.json");
43438
43949
  }
43439
43950
  loadCloneMeta() {
43440
43951
  const p = _VoiceEngine.cloneMetaFile();
43441
- if (!existsSync40(p))
43952
+ if (!existsSync41(p))
43442
43953
  return {};
43443
43954
  try {
43444
- return JSON.parse(readFileSync29(p, "utf8"));
43955
+ return JSON.parse(readFileSync30(p, "utf8"));
43445
43956
  } catch {
43446
43957
  return {};
43447
43958
  }
43448
43959
  }
43449
43960
  saveCloneMeta(meta) {
43450
43961
  const dir = luxttsCloneRefsDir();
43451
- if (!existsSync40(dir))
43452
- mkdirSync16(dir, { recursive: true });
43453
- writeFileSync17(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
43962
+ if (!existsSync41(dir))
43963
+ mkdirSync17(dir, { recursive: true });
43964
+ writeFileSync18(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
43454
43965
  }
43455
43966
  /** Audio file extensions recognized as clone references */
43456
43967
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -43460,7 +43971,7 @@ var init_voice = __esm({
43460
43971
  */
43461
43972
  listCloneRefs() {
43462
43973
  const dir = luxttsCloneRefsDir();
43463
- if (!existsSync40(dir))
43974
+ if (!existsSync41(dir))
43464
43975
  return [];
43465
43976
  const meta = this.loadCloneMeta();
43466
43977
  const files = readdirSync11(dir).filter((f) => {
@@ -43468,7 +43979,7 @@ var init_voice = __esm({
43468
43979
  return _VoiceEngine.AUDIO_EXTS.has(ext);
43469
43980
  });
43470
43981
  return files.map((f) => {
43471
- const p = join56(dir, f);
43982
+ const p = join57(dir, f);
43472
43983
  let size = 0;
43473
43984
  try {
43474
43985
  size = statSync13(p).size;
@@ -43485,8 +43996,8 @@ var init_voice = __esm({
43485
43996
  }
43486
43997
  /** Delete a clone reference file by filename. Returns true if deleted. */
43487
43998
  deleteCloneRef(filename) {
43488
- const p = join56(luxttsCloneRefsDir(), filename);
43489
- if (!existsSync40(p))
43999
+ const p = join57(luxttsCloneRefsDir(), filename);
44000
+ if (!existsSync41(p))
43490
44001
  return false;
43491
44002
  try {
43492
44003
  unlinkSync9(p);
@@ -43510,8 +44021,8 @@ var init_voice = __esm({
43510
44021
  }
43511
44022
  /** Set the active clone reference by filename. */
43512
44023
  setActiveCloneRef(filename) {
43513
- const p = join56(luxttsCloneRefsDir(), filename);
43514
- if (!existsSync40(p))
44024
+ const p = join57(luxttsCloneRefsDir(), filename);
44025
+ if (!existsSync41(p))
43515
44026
  return `File not found: ${filename}`;
43516
44027
  this.luxttsCloneRef = p;
43517
44028
  return `Active clone voice set to: ${filename}`;
@@ -43836,7 +44347,7 @@ var init_voice = __esm({
43836
44347
  }
43837
44348
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
43838
44349
  }
43839
- const wavPath = join56(tmpdir9(), `oa-voice-${Date.now()}.wav`);
44350
+ const wavPath = join57(tmpdir9(), `oa-voice-${Date.now()}.wav`);
43840
44351
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
43841
44352
  await this.playWav(wavPath);
43842
44353
  try {
@@ -43953,7 +44464,7 @@ var init_voice = __esm({
43953
44464
  buffer.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
43954
44465
  pos += 2;
43955
44466
  }
43956
- writeFileSync17(path, buffer);
44467
+ writeFileSync18(path, buffer);
43957
44468
  }
43958
44469
  // -------------------------------------------------------------------------
43959
44470
  // Phonemization
@@ -44031,7 +44542,7 @@ var init_voice = __esm({
44031
44542
  return buffer;
44032
44543
  }
44033
44544
  writeWav(samples, sampleRate, path) {
44034
- writeFileSync17(path, this.buildWavBuffer(samples, sampleRate));
44545
+ writeFileSync18(path, this.buildWavBuffer(samples, sampleRate));
44035
44546
  }
44036
44547
  // -------------------------------------------------------------------------
44037
44548
  // Audio playback (system default speakers)
@@ -44229,7 +44740,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44229
44740
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
44230
44741
  const mlxVoice = model.mlxVoice ?? "af_heart";
44231
44742
  const mlxLangCode = model.mlxLangCode ?? "a";
44232
- const wavPath = join56(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
44743
+ const wavPath = join57(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
44233
44744
  const pyScript = [
44234
44745
  "import sys, json",
44235
44746
  "from mlx_audio.tts import generate as tts_gen",
@@ -44246,11 +44757,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44246
44757
  return;
44247
44758
  }
44248
44759
  }
44249
- if (!existsSync40(wavPath))
44760
+ if (!existsSync41(wavPath))
44250
44761
  return;
44251
44762
  if (volume !== 1) {
44252
44763
  try {
44253
- const wavData = readFileSync29(wavPath);
44764
+ const wavData = readFileSync30(wavPath);
44254
44765
  if (wavData.length > 44) {
44255
44766
  const header = wavData.subarray(0, 44);
44256
44767
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -44258,14 +44769,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44258
44769
  samples[i] = Math.round(samples[i] * volume);
44259
44770
  }
44260
44771
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
44261
- writeFileSync17(wavPath, scaled);
44772
+ writeFileSync18(wavPath, scaled);
44262
44773
  }
44263
44774
  } catch {
44264
44775
  }
44265
44776
  }
44266
44777
  if (this.onPCMOutput) {
44267
44778
  try {
44268
- const wavData = readFileSync29(wavPath);
44779
+ const wavData = readFileSync30(wavPath);
44269
44780
  if (wavData.length > 44) {
44270
44781
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
44271
44782
  const sampleRate = wavData.readUInt32LE(24);
@@ -44297,7 +44808,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44297
44808
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
44298
44809
  const mlxVoice = model.mlxVoice ?? "af_heart";
44299
44810
  const mlxLangCode = model.mlxLangCode ?? "a";
44300
- const wavPath = join56(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
44811
+ const wavPath = join57(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
44301
44812
  const pyScript = [
44302
44813
  "import sys, json",
44303
44814
  "from mlx_audio.tts import generate as tts_gen",
@@ -44314,10 +44825,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44314
44825
  return null;
44315
44826
  }
44316
44827
  }
44317
- if (!existsSync40(wavPath))
44828
+ if (!existsSync41(wavPath))
44318
44829
  return null;
44319
44830
  try {
44320
- const data = readFileSync29(wavPath);
44831
+ const data = readFileSync30(wavPath);
44321
44832
  unlinkSync9(wavPath);
44322
44833
  return data;
44323
44834
  } catch {
@@ -44340,7 +44851,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44340
44851
  }
44341
44852
  const venvDir = luxttsVenvDir();
44342
44853
  const venvPy = luxttsVenvPy();
44343
- if (existsSync40(venvPy)) {
44854
+ if (existsSync41(venvPy)) {
44344
44855
  try {
44345
44856
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
44346
44857
  let hasCudaSys = false;
@@ -44354,7 +44865,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44354
44865
  if (torchCheck === "cpu") {
44355
44866
  renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
44356
44867
  try {
44357
- const detectScript = join56(voiceDir(), "detect-torch.py");
44868
+ const detectScript = join57(voiceDir(), "detect-torch.py");
44358
44869
  writeDetectTorchScript(detectScript);
44359
44870
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
44360
44871
  try {
@@ -44379,7 +44890,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44379
44890
  }
44380
44891
  }
44381
44892
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
44382
- if (!existsSync40(venvDir)) {
44893
+ if (!existsSync41(venvDir)) {
44383
44894
  renderInfo(" Creating Python virtual environment...");
44384
44895
  try {
44385
44896
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -44388,7 +44899,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44388
44899
  }
44389
44900
  }
44390
44901
  {
44391
- const detectScript = join56(voiceDir(), "detect-torch.py");
44902
+ const detectScript = join57(voiceDir(), "detect-torch.py");
44392
44903
  writeDetectTorchScript(detectScript);
44393
44904
  let pipArgsStr = "torch torchaudio";
44394
44905
  let torchDesc = "unknown platform";
@@ -44425,10 +44936,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44425
44936
  }
44426
44937
  }
44427
44938
  const repoDir = luxttsRepoDir();
44428
- if (!existsSync40(join56(repoDir, "zipvoice", "luxvoice.py"))) {
44939
+ if (!existsSync41(join57(repoDir, "zipvoice", "luxvoice.py"))) {
44429
44940
  renderInfo(" Cloning LuxTTS repository...");
44430
44941
  try {
44431
- if (existsSync40(repoDir)) {
44942
+ if (existsSync41(repoDir)) {
44432
44943
  const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
44433
44944
  await this.asyncShell(rmCmd, 3e4);
44434
44945
  }
@@ -44467,7 +44978,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44467
44978
  renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
44468
44979
  }
44469
44980
  }
44470
- const isJetson = isArm && (existsSync40("/etc/nv_tegra_release") || existsSync40("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
44981
+ const isJetson = isArm && (existsSync41("/etc/nv_tegra_release") || existsSync41("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
44471
44982
  const installSteps = isArm ? [
44472
44983
  // ARM: install individually so we get clear error messages per package.
44473
44984
  // ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
@@ -44535,14 +45046,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
44535
45046
  }
44536
45047
  /** Auto-detect an existing clone reference in the refs directory */
44537
45048
  autoDetectCloneRef() {
44538
- if (this.luxttsCloneRef && existsSync40(this.luxttsCloneRef))
45049
+ if (this.luxttsCloneRef && existsSync41(this.luxttsCloneRef))
44539
45050
  return;
44540
45051
  const refsDir = luxttsCloneRefsDir();
44541
- if (!existsSync40(refsDir))
45052
+ if (!existsSync41(refsDir))
44542
45053
  return;
44543
45054
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
44544
- const p = join56(refsDir, name);
44545
- if (existsSync40(p)) {
45055
+ const p = join57(refsDir, name);
45056
+ if (existsSync41(p)) {
44546
45057
  this.luxttsCloneRef = p;
44547
45058
  return;
44548
45059
  }
@@ -44642,15 +45153,15 @@ if __name__ == '__main__':
44642
45153
  main()
44643
45154
  `;
44644
45155
  const scriptPath2 = luxttsInferScript();
44645
- mkdirSync16(voiceDir(), { recursive: true });
44646
- writeFileSync17(scriptPath2, script);
45156
+ mkdirSync17(voiceDir(), { recursive: true });
45157
+ writeFileSync18(scriptPath2, script);
44647
45158
  }
44648
45159
  /** Ensure the LuxTTS daemon is running, spawn if needed */
44649
45160
  async ensureLuxttsDaemon() {
44650
45161
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
44651
45162
  return true;
44652
45163
  const venvPy = luxttsVenvPy();
44653
- if (!existsSync40(venvPy))
45164
+ if (!existsSync41(venvPy))
44654
45165
  return false;
44655
45166
  return new Promise((resolve35) => {
44656
45167
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
@@ -44734,7 +45245,7 @@ if __name__ == '__main__':
44734
45245
  * Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
44735
45246
  */
44736
45247
  async synthesizeLuxttsWav(text, speedFactor = 1) {
44737
- if (!this.luxttsCloneRef || !existsSync40(this.luxttsCloneRef))
45248
+ if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
44738
45249
  return null;
44739
45250
  const cleaned = text.replace(/\*/g, "").trim();
44740
45251
  if (!cleaned)
@@ -44742,7 +45253,7 @@ if __name__ == '__main__':
44742
45253
  const ready = await this.ensureLuxttsDaemon();
44743
45254
  if (!ready)
44744
45255
  return null;
44745
- const wavPath = join56(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
45256
+ const wavPath = join57(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
44746
45257
  try {
44747
45258
  await this.luxttsRequest({
44748
45259
  action: "synthesize",
@@ -44754,17 +45265,17 @@ if __name__ == '__main__':
44754
45265
  } catch {
44755
45266
  return null;
44756
45267
  }
44757
- return existsSync40(wavPath) ? wavPath : null;
45268
+ return existsSync41(wavPath) ? wavPath : null;
44758
45269
  }
44759
45270
  /**
44760
45271
  * Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
44761
45272
  * Cleans up the WAV file after playback.
44762
45273
  */
44763
45274
  async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
44764
- if (!existsSync40(wavPath))
45275
+ if (!existsSync41(wavPath))
44765
45276
  return;
44766
45277
  try {
44767
- const wavData = readFileSync29(wavPath);
45278
+ const wavData = readFileSync30(wavPath);
44768
45279
  if (wavData.length > 44) {
44769
45280
  const sampleRate = wavData.readUInt32LE(24);
44770
45281
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -44779,13 +45290,13 @@ if __name__ == '__main__':
44779
45290
  }
44780
45291
  const header = wavData.subarray(0, 44);
44781
45292
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
44782
- writeFileSync17(wavPath, scaled);
45293
+ writeFileSync18(wavPath, scaled);
44783
45294
  }
44784
45295
  } catch {
44785
45296
  }
44786
45297
  if (pitchFactor !== 1) {
44787
45298
  try {
44788
- const wavData = readFileSync29(wavPath);
45299
+ const wavData = readFileSync30(wavPath);
44789
45300
  if (wavData.length > 44) {
44790
45301
  const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
44791
45302
  const float32 = new Float32Array(int16.length);
@@ -44800,7 +45311,7 @@ if __name__ == '__main__':
44800
45311
  }
44801
45312
  if (this.onPCMOutput) {
44802
45313
  try {
44803
- const wavData = readFileSync29(wavPath);
45314
+ const wavData = readFileSync30(wavPath);
44804
45315
  if (wavData.length > 44) {
44805
45316
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
44806
45317
  const sampleRate = wavData.readUInt32LE(24);
@@ -44811,7 +45322,7 @@ if __name__ == '__main__':
44811
45322
  }
44812
45323
  if (stereoDelayMs > 0) {
44813
45324
  try {
44814
- const wavData = readFileSync29(wavPath);
45325
+ const wavData = readFileSync30(wavPath);
44815
45326
  if (wavData.length > 44) {
44816
45327
  const sampleRate = wavData.readUInt32LE(24);
44817
45328
  const numChannels = wavData.readUInt16LE(22);
@@ -44847,7 +45358,7 @@ if __name__ == '__main__':
44847
45358
  * Used for Telegram voice messages and WebSocket streaming.
44848
45359
  */
44849
45360
  async synthesizeLuxttsToBuffer(text) {
44850
- if (!this.luxttsCloneRef || !existsSync40(this.luxttsCloneRef))
45361
+ if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
44851
45362
  return null;
44852
45363
  const cleaned = text.replace(/\*/g, "").trim();
44853
45364
  if (!cleaned)
@@ -44855,7 +45366,7 @@ if __name__ == '__main__':
44855
45366
  const ready = await this.ensureLuxttsDaemon();
44856
45367
  if (!ready)
44857
45368
  return null;
44858
- const wavPath = join56(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
45369
+ const wavPath = join57(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
44859
45370
  try {
44860
45371
  await this.luxttsRequest({
44861
45372
  action: "synthesize",
@@ -44867,10 +45378,10 @@ if __name__ == '__main__':
44867
45378
  } catch {
44868
45379
  return null;
44869
45380
  }
44870
- if (!existsSync40(wavPath))
45381
+ if (!existsSync41(wavPath))
44871
45382
  return null;
44872
45383
  try {
44873
- const data = readFileSync29(wavPath);
45384
+ const data = readFileSync30(wavPath);
44874
45385
  unlinkSync9(wavPath);
44875
45386
  return data;
44876
45387
  } catch {
@@ -44884,40 +45395,40 @@ if __name__ == '__main__':
44884
45395
  if (this.ort)
44885
45396
  return;
44886
45397
  const arch2 = process.arch;
44887
- mkdirSync16(voiceDir(), { recursive: true });
44888
- const pkgPath = join56(voiceDir(), "package.json");
45398
+ mkdirSync17(voiceDir(), { recursive: true });
45399
+ const pkgPath = join57(voiceDir(), "package.json");
44889
45400
  const expectedDeps = {
44890
45401
  "onnxruntime-node": "^1.21.0",
44891
45402
  "phonemizer": "^1.2.1"
44892
45403
  };
44893
- if (existsSync40(pkgPath)) {
45404
+ if (existsSync41(pkgPath)) {
44894
45405
  try {
44895
- const existing = JSON.parse(readFileSync29(pkgPath, "utf8"));
45406
+ const existing = JSON.parse(readFileSync30(pkgPath, "utf8"));
44896
45407
  if (!existing.dependencies?.["phonemizer"]) {
44897
45408
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
44898
- writeFileSync17(pkgPath, JSON.stringify(existing, null, 2));
45409
+ writeFileSync18(pkgPath, JSON.stringify(existing, null, 2));
44899
45410
  }
44900
45411
  } catch {
44901
45412
  }
44902
45413
  }
44903
- if (!existsSync40(pkgPath)) {
44904
- writeFileSync17(pkgPath, JSON.stringify({
45414
+ if (!existsSync41(pkgPath)) {
45415
+ writeFileSync18(pkgPath, JSON.stringify({
44905
45416
  name: "open-agents-voice",
44906
45417
  private: true,
44907
45418
  dependencies: expectedDeps
44908
45419
  }, null, 2));
44909
45420
  }
44910
- const voiceRequire = createRequire(join56(voiceDir(), "index.js"));
45421
+ const voiceRequire = createRequire(join57(voiceDir(), "index.js"));
44911
45422
  const probeOnnx = async () => {
44912
45423
  try {
44913
- const output = await this.asyncShell(`NODE_PATH="${join56(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
45424
+ const output = await this.asyncShell(`NODE_PATH="${join57(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
44914
45425
  return output.trim() === "OK";
44915
45426
  } catch {
44916
45427
  return false;
44917
45428
  }
44918
45429
  };
44919
- const onnxNodeModules = join56(voiceDir(), "node_modules", "onnxruntime-node");
44920
- const onnxInstalled = existsSync40(onnxNodeModules);
45430
+ const onnxNodeModules = join57(voiceDir(), "node_modules", "onnxruntime-node");
45431
+ const onnxInstalled = existsSync41(onnxNodeModules);
44921
45432
  if (onnxInstalled && !await probeOnnx()) {
44922
45433
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
44923
45434
  }
@@ -44966,19 +45477,19 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
44966
45477
  throw new Error(`Unknown model: ${id}`);
44967
45478
  const dir = modelDir(id);
44968
45479
  const onnxPath = modelOnnxPath(id);
44969
- const configPath = modelConfigPath(id);
44970
- if (existsSync40(onnxPath) && existsSync40(configPath))
45480
+ const configPath2 = modelConfigPath(id);
45481
+ if (existsSync41(onnxPath) && existsSync41(configPath2))
44971
45482
  return;
44972
- mkdirSync16(dir, { recursive: true });
44973
- if (!existsSync40(configPath)) {
45483
+ mkdirSync17(dir, { recursive: true });
45484
+ if (!existsSync41(configPath2)) {
44974
45485
  renderInfo(`Downloading ${model.label} voice config...`);
44975
45486
  const configResp = await fetch(model.configUrl);
44976
45487
  if (!configResp.ok)
44977
45488
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
44978
45489
  const configText = await configResp.text();
44979
- writeFileSync17(configPath, configText);
45490
+ writeFileSync18(configPath2, configText);
44980
45491
  }
44981
- if (!existsSync40(onnxPath)) {
45492
+ if (!existsSync41(onnxPath)) {
44982
45493
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
44983
45494
  const onnxResp = await fetch(model.onnxUrl);
44984
45495
  if (!onnxResp.ok)
@@ -45003,7 +45514,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
45003
45514
  }
45004
45515
  }
45005
45516
  const fullBuffer = Buffer.concat(chunks);
45006
- writeFileSync17(onnxPath, fullBuffer);
45517
+ writeFileSync18(onnxPath, fullBuffer);
45007
45518
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
45008
45519
  }
45009
45520
  }
@@ -45014,11 +45525,11 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
45014
45525
  if (!this.ort)
45015
45526
  throw new Error("ONNX runtime not loaded");
45016
45527
  const onnxPath = modelOnnxPath(this.modelId);
45017
- const configPath = modelConfigPath(this.modelId);
45018
- if (!existsSync40(onnxPath) || !existsSync40(configPath)) {
45528
+ const configPath2 = modelConfigPath(this.modelId);
45529
+ if (!existsSync41(onnxPath) || !existsSync41(configPath2)) {
45019
45530
  throw new Error(`Model files not found for ${this.modelId}`);
45020
45531
  }
45021
- this.config = JSON.parse(readFileSync29(configPath, "utf8"));
45532
+ this.config = JSON.parse(readFileSync30(configPath2, "utf8"));
45022
45533
  this.session = await this.ort.InferenceSession.create(onnxPath, {
45023
45534
  executionProviders: ["cpu"],
45024
45535
  graphOptimizationLevel: "all"
@@ -45045,8 +45556,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
45045
45556
  // packages/cli/dist/tui/commands.js
45046
45557
  import * as nodeOs from "node:os";
45047
45558
  import { execSync as nodeExecSync } from "node:child_process";
45048
- import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
45049
- import { join as join57 } from "node:path";
45559
+ import { existsSync as existsSync42, readFileSync as readFileSync31, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
45560
+ import { join as join58 } from "node:path";
45050
45561
  function safeLog(text) {
45051
45562
  if (isNeovimActive()) {
45052
45563
  writeToNeovimOutput(text + "\n");
@@ -45655,22 +46166,22 @@ async function handleSlashCommand(input, ctx) {
45655
46166
  let content = "";
45656
46167
  let metadata = {};
45657
46168
  if (shareType === "tool") {
45658
- const toolDir = join57(ctx.repoRoot, ".oa", "tools");
45659
- const toolFile = join57(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
45660
- if (!existsSync41(toolFile)) {
46169
+ const toolDir = join58(ctx.repoRoot, ".oa", "tools");
46170
+ const toolFile = join58(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
46171
+ if (!existsSync42(toolFile)) {
45661
46172
  renderWarning(`Tool not found: ${toolFile}`);
45662
46173
  return "handled";
45663
46174
  }
45664
- content = readFileSync30(toolFile, "utf8");
46175
+ content = readFileSync31(toolFile, "utf8");
45665
46176
  metadata = { type: "tool", name: shareName };
45666
46177
  } else if (shareType === "skill") {
45667
- const skillDir = join57(ctx.repoRoot, ".oa", "skills", shareName);
45668
- const skillFile = join57(skillDir, "SKILL.md");
45669
- if (!existsSync41(skillFile)) {
46178
+ const skillDir = join58(ctx.repoRoot, ".oa", "skills", shareName);
46179
+ const skillFile = join58(skillDir, "SKILL.md");
46180
+ if (!existsSync42(skillFile)) {
45670
46181
  renderWarning(`Skill not found: ${skillFile}`);
45671
46182
  return "handled";
45672
46183
  }
45673
- content = readFileSync30(skillFile, "utf8");
46184
+ content = readFileSync31(skillFile, "utf8");
45674
46185
  metadata = { type: "skill", name: shareName };
45675
46186
  } else {
45676
46187
  renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
@@ -45709,9 +46220,9 @@ async function handleSlashCommand(input, ctx) {
45709
46220
  const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
45710
46221
  const nexus = new NexusTool2(ctx.repoRoot);
45711
46222
  await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
45712
- const regFile = join57(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
45713
- if (existsSync41(regFile)) {
45714
- const reg = JSON.parse(readFileSync30(regFile, "utf8"));
46223
+ const regFile = join58(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
46224
+ if (existsSync42(regFile)) {
46225
+ const reg = JSON.parse(readFileSync31(regFile, "utf8"));
45715
46226
  const pinned = Object.values(reg).some((e) => e.cid === importCid && e.pinned);
45716
46227
  if (pinned) {
45717
46228
  renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
@@ -45764,33 +46275,33 @@ async function handleSlashCommand(input, ctx) {
45764
46275
  lines.push(`
45765
46276
  ${c2.bold("IPFS / Helia Status")}
45766
46277
  `);
45767
- const ipfsDir = join57(ctx.repoRoot, ".oa", "ipfs");
45768
- const ipfsLocalDir = join57(ipfsDir, "local");
46278
+ const ipfsDir = join58(ctx.repoRoot, ".oa", "ipfs");
46279
+ const ipfsLocalDir = join58(ipfsDir, "local");
45769
46280
  let ipfsFiles = 0;
45770
46281
  let ipfsBytes = 0;
45771
46282
  let heliaBlocks = 0;
45772
46283
  let heliaBytes = 0;
45773
46284
  try {
45774
- if (existsSync41(ipfsLocalDir)) {
46285
+ if (existsSync42(ipfsLocalDir)) {
45775
46286
  const files = readdirSync12(ipfsLocalDir).filter((f) => f.endsWith(".json"));
45776
46287
  ipfsFiles = files.length;
45777
46288
  for (const f of files) {
45778
46289
  try {
45779
- ipfsBytes += statSync14(join57(ipfsLocalDir, f)).size;
46290
+ ipfsBytes += statSync14(join58(ipfsLocalDir, f)).size;
45780
46291
  } catch {
45781
46292
  }
45782
46293
  }
45783
46294
  }
45784
- const heliaBlockDir = join57(ipfsDir, "blocks");
45785
- if (existsSync41(heliaBlockDir)) {
46295
+ const heliaBlockDir = join58(ipfsDir, "blocks");
46296
+ if (existsSync42(heliaBlockDir)) {
45786
46297
  const walkDir = (dir) => {
45787
46298
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
45788
46299
  if (entry.isDirectory())
45789
- walkDir(join57(dir, entry.name));
46300
+ walkDir(join58(dir, entry.name));
45790
46301
  else {
45791
46302
  heliaBlocks++;
45792
46303
  try {
45793
- heliaBytes += statSync14(join57(dir, entry.name)).size;
46304
+ heliaBytes += statSync14(join58(dir, entry.name)).size;
45794
46305
  } catch {
45795
46306
  }
45796
46307
  }
@@ -45806,9 +46317,9 @@ async function handleSlashCommand(input, ctx) {
45806
46317
  lines.push(` Blocks: ${c2.bold(String(heliaBlocks))} Size: ${c2.bold(formatFileSize(heliaBytes))}`);
45807
46318
  lines.push(` Backend: ${heliaBlocks > 0 ? c2.green("helia-ipfs") : c2.yellow("sha256-local (Helia not initialized)")}`);
45808
46319
  try {
45809
- const statusFile = join57(ctx.repoRoot, ".oa", "nexus", "status.json");
45810
- if (existsSync41(statusFile)) {
45811
- const status = JSON.parse(readFileSync30(statusFile, "utf8"));
46320
+ const statusFile = join58(ctx.repoRoot, ".oa", "nexus", "status.json");
46321
+ if (existsSync42(statusFile)) {
46322
+ const status = JSON.parse(readFileSync31(statusFile, "utf8"));
45812
46323
  if (status.peerId) {
45813
46324
  lines.push(`
45814
46325
  ${c2.bold("Peer Info")}`);
@@ -45827,11 +46338,11 @@ async function handleSlashCommand(input, ctx) {
45827
46338
  ${c2.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
45828
46339
  lines.push(`
45829
46340
  ${c2.bold("Identity Kernel")}`);
45830
- const idDir = join57(ctx.repoRoot, ".oa", "identity");
46341
+ const idDir = join58(ctx.repoRoot, ".oa", "identity");
45831
46342
  try {
45832
- const stateFile = join57(idDir, "self-state.json");
45833
- if (existsSync41(stateFile)) {
45834
- const state = JSON.parse(readFileSync30(stateFile, "utf8"));
46343
+ const stateFile = join58(idDir, "self-state.json");
46344
+ if (existsSync42(stateFile)) {
46345
+ const state = JSON.parse(readFileSync31(stateFile, "utf8"));
45835
46346
  lines.push(` Version: ${c2.bold("v" + (state.version ?? "?"))} Sessions: ${c2.bold(String(state.session_count ?? 0))}`);
45836
46347
  if (state.narrative_summary) {
45837
46348
  lines.push(` Narrative: ${c2.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
@@ -45840,9 +46351,9 @@ async function handleSlashCommand(input, ctx) {
45840
46351
  const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
45841
46352
  lines.push(` Traits: ${c2.dim(traits.slice(0, 60))}`);
45842
46353
  }
45843
- const cidFile = join57(idDir, "cids.json");
45844
- if (existsSync41(cidFile)) {
45845
- const cids = JSON.parse(readFileSync30(cidFile, "utf8"));
46354
+ const cidFile = join58(idDir, "cids.json");
46355
+ if (existsSync42(cidFile)) {
46356
+ const cids = JSON.parse(readFileSync31(cidFile, "utf8"));
45846
46357
  const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
45847
46358
  if (lastCid)
45848
46359
  lines.push(` Last CID: ${c2.dim(String(lastCid).slice(0, 50))}`);
@@ -45855,9 +46366,9 @@ async function handleSlashCommand(input, ctx) {
45855
46366
  lines.push(`
45856
46367
  ${c2.bold("Memory Sentiment")}`);
45857
46368
  try {
45858
- const metaFile = join57(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
45859
- if (existsSync41(metaFile)) {
45860
- const store = JSON.parse(readFileSync30(metaFile, "utf8"));
46369
+ const metaFile = join58(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
46370
+ if (existsSync42(metaFile)) {
46371
+ const store = JSON.parse(readFileSync31(metaFile, "utf8"));
45861
46372
  const active = store.filter((m) => m.type !== "quarantine");
45862
46373
  const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
45863
46374
  const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
@@ -45875,8 +46386,8 @@ async function handleSlashCommand(input, ctx) {
45875
46386
  } catch {
45876
46387
  }
45877
46388
  try {
45878
- const dbPath = join57(ctx.repoRoot, ".oa", "memory", "structured.db");
45879
- if (existsSync41(dbPath)) {
46389
+ const dbPath = join58(ctx.repoRoot, ".oa", "memory", "structured.db");
46390
+ if (existsSync42(dbPath)) {
45880
46391
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
45881
46392
  const db = initDb2(dbPath);
45882
46393
  const memStore = new ProceduralMemoryStore2(db);
@@ -45897,8 +46408,8 @@ async function handleSlashCommand(input, ctx) {
45897
46408
  lines.push(`
45898
46409
  ${c2.bold("Storage Overview")}
45899
46410
  `);
45900
- const oaDir = join57(ctx.repoRoot, ".oa");
45901
- if (!existsSync41(oaDir)) {
46411
+ const oaDir = join58(ctx.repoRoot, ".oa");
46412
+ if (!existsSync42(oaDir)) {
45902
46413
  lines.push(` ${c2.dim("No .oa/ directory found.")}`);
45903
46414
  safeLog(lines.join("\n") + "\n");
45904
46415
  return "handled";
@@ -45908,7 +46419,7 @@ async function handleSlashCommand(input, ctx) {
45908
46419
  const walkStorage = (dir, category) => {
45909
46420
  try {
45910
46421
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
45911
- const full = join57(dir, entry.name);
46422
+ const full = join58(dir, entry.name);
45912
46423
  if (entry.isDirectory()) {
45913
46424
  const subCat = category || entry.name;
45914
46425
  walkStorage(full, subCat);
@@ -45944,10 +46455,10 @@ async function handleSlashCommand(input, ctx) {
45944
46455
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
45945
46456
  const name = entry.name.toLowerCase();
45946
46457
  if (sensitivePatterns.some((p) => name.includes(p))) {
45947
- sensitiveFound.push(join57(dir, entry.name).replace(oaDir + "/", ""));
46458
+ sensitiveFound.push(join58(dir, entry.name).replace(oaDir + "/", ""));
45948
46459
  }
45949
46460
  if (entry.isDirectory())
45950
- checkSensitive(join57(dir, entry.name));
46461
+ checkSensitive(join58(dir, entry.name));
45951
46462
  }
45952
46463
  } catch {
45953
46464
  }
@@ -45975,8 +46486,8 @@ async function handleSlashCommand(input, ctx) {
45975
46486
  renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
45976
46487
  return "handled";
45977
46488
  }
45978
- const resolvedPath = join57(ctx.repoRoot, filePath);
45979
- if (!existsSync41(resolvedPath)) {
46489
+ const resolvedPath = join58(ctx.repoRoot, filePath);
46490
+ if (!existsSync42(resolvedPath)) {
45980
46491
  renderWarning(`File not found: ${resolvedPath}`);
45981
46492
  return "handled";
45982
46493
  }
@@ -45992,9 +46503,9 @@ async function handleSlashCommand(input, ctx) {
45992
46503
  }
45993
46504
  try {
45994
46505
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
45995
- const dbDir = join57(ctx.repoRoot, ".oa", "memory");
45996
- mkdirSync17(dbDir, { recursive: true });
45997
- const db = initDb2(join57(dbDir, "structured.db"));
46506
+ const dbDir = join58(ctx.repoRoot, ".oa", "memory");
46507
+ mkdirSync18(dbDir, { recursive: true });
46508
+ const db = initDb2(join58(dbDir, "structured.db"));
45998
46509
  const memStore = new ProceduralMemoryStore2(db);
45999
46510
  if (isAudio) {
46000
46511
  renderInfo(`Transcribing: ${filePath}...`);
@@ -46035,7 +46546,7 @@ async function handleSlashCommand(input, ctx) {
46035
46546
  return "handled";
46036
46547
  }
46037
46548
  } else {
46038
- content = readFileSync30(resolvedPath, "utf8");
46549
+ content = readFileSync31(resolvedPath, "utf8");
46039
46550
  }
46040
46551
  if (!content.trim()) {
46041
46552
  renderWarning("No content extracted.");
@@ -46074,9 +46585,9 @@ async function handleSlashCommand(input, ctx) {
46074
46585
  }
46075
46586
  case "fortemi": {
46076
46587
  const fortemiSubCmd = (arg || "").trim().toLowerCase();
46077
- const fortemiDir = join57(ctx.repoRoot, "..", "fortemi-react");
46078
- const altFortemiDir = join57(nodeOs.homedir(), "fortemi-react");
46079
- const fDir = existsSync41(fortemiDir) ? fortemiDir : existsSync41(altFortemiDir) ? altFortemiDir : null;
46588
+ const fortemiDir = join58(ctx.repoRoot, "..", "fortemi-react");
46589
+ const altFortemiDir = join58(nodeOs.homedir(), "fortemi-react");
46590
+ const fDir = existsSync42(fortemiDir) ? fortemiDir : existsSync42(altFortemiDir) ? altFortemiDir : null;
46080
46591
  if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
46081
46592
  if (!fDir) {
46082
46593
  renderWarning("fortemi-react not found adjacent or in home directory.");
@@ -46091,14 +46602,14 @@ async function handleSlashCommand(input, ctx) {
46091
46602
  // 24h
46092
46603
  nonce: Math.random().toString(36).slice(2, 10)
46093
46604
  };
46094
- const jwtFile = join57(ctx.repoRoot, ".oa", "fortemi-jwt.json");
46095
- mkdirSync17(join57(ctx.repoRoot, ".oa"), { recursive: true });
46096
- writeFileSync18(jwtFile, JSON.stringify(jwtPayload, null, 2));
46605
+ const jwtFile = join58(ctx.repoRoot, ".oa", "fortemi-jwt.json");
46606
+ mkdirSync18(join58(ctx.repoRoot, ".oa"), { recursive: true });
46607
+ writeFileSync19(jwtFile, JSON.stringify(jwtPayload, null, 2));
46097
46608
  renderInfo(`Launching fortemi-react from ${fDir}...`);
46098
46609
  try {
46099
46610
  const { spawn: spawn22 } = __require("node:child_process");
46100
46611
  const child = spawn22("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
46101
- cwd: join57(fDir, "apps", "standalone"),
46612
+ cwd: join58(fDir, "apps", "standalone"),
46102
46613
  stdio: "ignore",
46103
46614
  detached: true,
46104
46615
  env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
@@ -46107,8 +46618,8 @@ async function handleSlashCommand(input, ctx) {
46107
46618
  renderInfo("Fortemi-React starting on http://localhost:3000");
46108
46619
  renderInfo(`JWT saved to ${jwtFile}`);
46109
46620
  renderInfo("Memory operations will proxy to fortemi when available.");
46110
- const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46111
- writeFileSync18(bridgeFile, JSON.stringify({
46621
+ const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46622
+ writeFileSync19(bridgeFile, JSON.stringify({
46112
46623
  url: "http://localhost:3000",
46113
46624
  pid: child.pid,
46114
46625
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -46120,12 +46631,12 @@ async function handleSlashCommand(input, ctx) {
46120
46631
  return "handled";
46121
46632
  }
46122
46633
  if (fortemiSubCmd === "status") {
46123
- const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46124
- if (!existsSync41(bridgeFile)) {
46634
+ const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46635
+ if (!existsSync42(bridgeFile)) {
46125
46636
  renderInfo("Fortemi bridge: not connected. Run /fortemi start");
46126
46637
  return "handled";
46127
46638
  }
46128
- const bridge = JSON.parse(readFileSync30(bridgeFile, "utf8"));
46639
+ const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
46129
46640
  let alive = false;
46130
46641
  try {
46131
46642
  process.kill(bridge.pid, 0);
@@ -46145,15 +46656,15 @@ async function handleSlashCommand(input, ctx) {
46145
46656
  lines.push(` Process: ${alive ? c2.green("running") : c2.yellow("not running")} (PID ${bridge.pid})`);
46146
46657
  lines.push(` HTTP: ${httpOk ? c2.green("connected") : c2.yellow("unreachable")}`);
46147
46658
  lines.push(` Started: ${bridge.startedAt}`);
46148
- lines.push(` JWT: ${existsSync41(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
46659
+ lines.push(` JWT: ${existsSync42(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
46149
46660
  lines.push("");
46150
46661
  safeLog(lines.join("\n"));
46151
46662
  return "handled";
46152
46663
  }
46153
46664
  if (fortemiSubCmd === "stop") {
46154
- const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46155
- if (existsSync41(bridgeFile)) {
46156
- const bridge = JSON.parse(readFileSync30(bridgeFile, "utf8"));
46665
+ const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
46666
+ if (existsSync42(bridgeFile)) {
46667
+ const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
46157
46668
  try {
46158
46669
  process.kill(bridge.pid, "SIGTERM");
46159
46670
  } catch {
@@ -46531,6 +47042,86 @@ async function handleSlashCommand(input, ctx) {
46531
47042
  }
46532
47043
  return "handled";
46533
47044
  }
47045
+ case "sponsor": {
47046
+ if (!ctx.rl) {
47047
+ renderWarning("Sponsor wizard requires interactive mode.");
47048
+ return "handled";
47049
+ }
47050
+ const { loadSponsorConfig: loadSponsorConfig2, saveSponsorConfig: saveSponsorConfig2, runSponsorWizard: runSponsorWizard2, showSponsorDashboard: showSponsorDashboard2 } = await Promise.resolve().then(() => (init_sponsor_wizard(), sponsor_wizard_exports));
47051
+ const projectDir = process.cwd();
47052
+ const existingConfig = loadSponsorConfig2(projectDir);
47053
+ const sponsorRl = ctx.rl;
47054
+ if (arg === "pause" && existingConfig?.status === "active") {
47055
+ existingConfig.status = "paused";
47056
+ saveSponsorConfig2(projectDir, existingConfig);
47057
+ renderInfo("Sponsorship paused. /sponsor to resume.");
47058
+ return "handled";
47059
+ }
47060
+ if (arg === "remove" && existingConfig) {
47061
+ existingConfig.status = "inactive";
47062
+ saveSponsorConfig2(projectDir, existingConfig);
47063
+ renderInfo("Sponsorship removed.");
47064
+ return "handled";
47065
+ }
47066
+ if (arg === "status" || existingConfig && existingConfig.status !== "inactive") {
47067
+ if (!existingConfig || existingConfig.status === "inactive") {
47068
+ renderInfo("No active sponsorship. Run /sponsor to start.");
47069
+ return "handled";
47070
+ }
47071
+ const action = await showSponsorDashboard2(existingConfig, projectDir, sponsorRl, ctx.availableContentRows?.());
47072
+ switch (action) {
47073
+ case "modify":
47074
+ break;
47075
+ case "pause":
47076
+ existingConfig.status = "paused";
47077
+ saveSponsorConfig2(projectDir, existingConfig);
47078
+ renderInfo("Sponsorship paused. /sponsor to resume.");
47079
+ return "handled";
47080
+ case "resume":
47081
+ existingConfig.status = "active";
47082
+ saveSponsorConfig2(projectDir, existingConfig);
47083
+ renderInfo("Sponsorship resumed.");
47084
+ return "handled";
47085
+ case "remove":
47086
+ existingConfig.status = "inactive";
47087
+ saveSponsorConfig2(projectDir, existingConfig);
47088
+ renderInfo("Sponsorship removed.");
47089
+ return "handled";
47090
+ default:
47091
+ return "handled";
47092
+ }
47093
+ }
47094
+ const result = await runSponsorWizard2({
47095
+ rl: sponsorRl,
47096
+ projectDir,
47097
+ ollamaUrl: "http://localhost:11434",
47098
+ availableRows: ctx.availableContentRows?.(),
47099
+ onGoLive: async (config) => {
47100
+ if (config.transport.cloudflared && ctx.exposeStart) {
47101
+ try {
47102
+ const url = await ctx.exposeStart("ollama", void 0, "tunnel");
47103
+ if (url)
47104
+ renderInfo(`Tunnel: ${url}`);
47105
+ } catch (err) {
47106
+ renderError(`Tunnel start failed: ${err instanceof Error ? err.message : String(err)}`);
47107
+ }
47108
+ }
47109
+ if (config.transport.libp2p && ctx.exposeStart) {
47110
+ try {
47111
+ const url = await ctx.exposeStart("ollama", void 0, "libp2p");
47112
+ if (url)
47113
+ renderInfo(`P2P: ${url}`);
47114
+ } catch (err) {
47115
+ renderError(`P2P start failed: ${err instanceof Error ? err.message : String(err)}`);
47116
+ }
47117
+ }
47118
+ }
47119
+ });
47120
+ if (result) {
47121
+ renderInfo("Sponsor wizard completed.");
47122
+ }
47123
+ return "handled";
47124
+ }
46534
47125
  case "expose": {
46535
47126
  if (!ctx.exposeStart) {
46536
47127
  renderWarning("Expose gateway not available in this context.");
@@ -47532,13 +48123,13 @@ async function showCohereDashboard(ctx) {
47532
48123
  } else if (idResult.key === "view") {
47533
48124
  await ik.execute({ operation: "hydrate" });
47534
48125
  } else if (idResult.key === "history") {
47535
- const snapDir = join57(ctx.repoRoot, ".oa", "identity", "snapshots");
47536
- if (existsSync41(snapDir)) {
48126
+ const snapDir = join58(ctx.repoRoot, ".oa", "identity", "snapshots");
48127
+ if (existsSync42(snapDir)) {
47537
48128
  const snaps = readdirSync12(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
47538
48129
  const snapItems = snaps.slice(0, 20).map((f) => ({
47539
48130
  key: f,
47540
48131
  label: f.replace(".json", ""),
47541
- detail: `${formatFileSize(statSync14(join57(snapDir, f)).size)}`
48132
+ detail: `${formatFileSize(statSync14(join58(snapDir, f)).size)}`
47542
48133
  }));
47543
48134
  if (snapItems.length > 0) {
47544
48135
  await tuiSelect({
@@ -47854,12 +48445,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
47854
48445
  continue;
47855
48446
  }
47856
48447
  const { basename: basename18, join: pathJoin } = await import("node:path");
47857
- const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync26, existsSync: exists } = await import("node:fs");
48448
+ const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync27, existsSync: exists } = await import("node:fs");
47858
48449
  const { homedir: homedir18 } = await import("node:os");
47859
48450
  const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
47860
48451
  const destDir = pathJoin(homedir18(), ".open-agents", "voice", "models", modelName);
47861
48452
  if (!exists(destDir))
47862
- mkdirSync26(destDir, { recursive: true });
48453
+ mkdirSync27(destDir, { recursive: true });
47863
48454
  copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
47864
48455
  copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
47865
48456
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -48351,11 +48942,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
48351
48942
  const models = await fetchModels(peerUrl, authKey);
48352
48943
  if (models.length > 0) {
48353
48944
  try {
48354
- const { writeFileSync: writeFileSync25, mkdirSync: mkdirSync26 } = await import("node:fs");
48355
- const { join: join72, dirname: dirname22 } = await import("node:path");
48356
- const cachePath = join72(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
48357
- mkdirSync26(dirname22(cachePath), { recursive: true });
48358
- writeFileSync25(cachePath, JSON.stringify({
48945
+ const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync27 } = await import("node:fs");
48946
+ const { join: join73, dirname: dirname22 } = await import("node:path");
48947
+ const cachePath = join73(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
48948
+ mkdirSync27(dirname22(cachePath), { recursive: true });
48949
+ writeFileSync26(cachePath, JSON.stringify({
48359
48950
  peerId,
48360
48951
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
48361
48952
  models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
@@ -48554,17 +49145,17 @@ async function handleUpdate(subcommand, ctx) {
48554
49145
  try {
48555
49146
  const { createRequire: createRequire4 } = await import("node:module");
48556
49147
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
48557
- const { dirname: dirname22, join: join72 } = await import("node:path");
48558
- const { existsSync: existsSync52 } = await import("node:fs");
49148
+ const { dirname: dirname22, join: join73 } = await import("node:path");
49149
+ const { existsSync: existsSync53 } = await import("node:fs");
48559
49150
  const req = createRequire4(import.meta.url);
48560
49151
  const thisDir = dirname22(fileURLToPath14(import.meta.url));
48561
49152
  const candidates = [
48562
- join72(thisDir, "..", "package.json"),
48563
- join72(thisDir, "..", "..", "package.json"),
48564
- join72(thisDir, "..", "..", "..", "package.json")
49153
+ join73(thisDir, "..", "package.json"),
49154
+ join73(thisDir, "..", "..", "package.json"),
49155
+ join73(thisDir, "..", "..", "..", "package.json")
48565
49156
  ];
48566
49157
  for (const pkgPath of candidates) {
48567
- if (existsSync52(pkgPath)) {
49158
+ if (existsSync53(pkgPath)) {
48568
49159
  const pkg = req(pkgPath);
48569
49160
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
48570
49161
  currentVersion = pkg.version ?? "0.0.0";
@@ -49402,8 +49993,8 @@ var init_commands = __esm({
49402
49993
  });
49403
49994
 
49404
49995
  // packages/cli/dist/tui/project-context.js
49405
- import { existsSync as existsSync42, readFileSync as readFileSync31, readdirSync as readdirSync13 } from "node:fs";
49406
- import { join as join58, basename as basename12 } from "node:path";
49996
+ import { existsSync as existsSync43, readFileSync as readFileSync32, readdirSync as readdirSync13 } from "node:fs";
49997
+ import { join as join59, basename as basename12 } from "node:path";
49407
49998
  import { execSync as execSync30 } from "node:child_process";
49408
49999
  import { homedir as homedir15, platform as platform4, release } from "node:os";
49409
50000
  function getModelTier(modelName) {
@@ -49438,10 +50029,10 @@ function loadProjectMap(repoRoot) {
49438
50029
  if (!hasOaDirectory(repoRoot)) {
49439
50030
  initOaDirectory(repoRoot);
49440
50031
  }
49441
- const mapPath2 = join58(repoRoot, OA_DIR, "context", "project-map.md");
49442
- if (existsSync42(mapPath2)) {
50032
+ const mapPath2 = join59(repoRoot, OA_DIR, "context", "project-map.md");
50033
+ if (existsSync43(mapPath2)) {
49443
50034
  try {
49444
- const content = readFileSync31(mapPath2, "utf-8");
50035
+ const content = readFileSync32(mapPath2, "utf-8");
49445
50036
  return content;
49446
50037
  } catch {
49447
50038
  }
@@ -49482,31 +50073,31 @@ ${log}`);
49482
50073
  }
49483
50074
  function loadMemoryContext(repoRoot) {
49484
50075
  const sections = [];
49485
- const oaMemDir = join58(repoRoot, OA_DIR, "memory");
50076
+ const oaMemDir = join59(repoRoot, OA_DIR, "memory");
49486
50077
  const oaEntries = loadMemoryDir(oaMemDir, "project");
49487
50078
  if (oaEntries)
49488
50079
  sections.push(oaEntries);
49489
- const legacyMemDir = join58(repoRoot, ".open-agents", "memory");
49490
- if (legacyMemDir !== oaMemDir && existsSync42(legacyMemDir)) {
50080
+ const legacyMemDir = join59(repoRoot, ".open-agents", "memory");
50081
+ if (legacyMemDir !== oaMemDir && existsSync43(legacyMemDir)) {
49491
50082
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
49492
50083
  if (legacyEntries)
49493
50084
  sections.push(legacyEntries);
49494
50085
  }
49495
- const globalMemDir = join58(homedir15(), ".open-agents", "memory");
50086
+ const globalMemDir = join59(homedir15(), ".open-agents", "memory");
49496
50087
  const globalEntries = loadMemoryDir(globalMemDir, "global");
49497
50088
  if (globalEntries)
49498
50089
  sections.push(globalEntries);
49499
50090
  return sections.join("\n\n");
49500
50091
  }
49501
50092
  function loadMemoryDir(memDir, scope) {
49502
- if (!existsSync42(memDir))
50093
+ if (!existsSync43(memDir))
49503
50094
  return "";
49504
50095
  const lines = [];
49505
50096
  try {
49506
50097
  const files = readdirSync13(memDir).filter((f) => f.endsWith(".json"));
49507
50098
  for (const file of files.slice(0, 10)) {
49508
50099
  try {
49509
- const raw = readFileSync31(join58(memDir, file), "utf-8");
50100
+ const raw = readFileSync32(join59(memDir, file), "utf-8");
49510
50101
  const entries = JSON.parse(raw);
49511
50102
  const topic = basename12(file, ".json");
49512
50103
  const keys = Object.keys(entries);
@@ -51025,22 +51616,22 @@ var init_banner = __esm({
51025
51616
  });
51026
51617
 
51027
51618
  // packages/cli/dist/tui/carousel-descriptors.js
51028
- import { existsSync as existsSync43, readFileSync as readFileSync32, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync14 } from "node:fs";
51029
- import { join as join59, basename as basename13 } from "node:path";
51619
+ import { existsSync as existsSync44, readFileSync as readFileSync33, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync14 } from "node:fs";
51620
+ import { join as join60, basename as basename13 } from "node:path";
51030
51621
  function loadToolProfile(repoRoot) {
51031
- const filePath = join59(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
51622
+ const filePath = join60(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
51032
51623
  try {
51033
- if (!existsSync43(filePath))
51624
+ if (!existsSync44(filePath))
51034
51625
  return null;
51035
- return JSON.parse(readFileSync32(filePath, "utf-8"));
51626
+ return JSON.parse(readFileSync33(filePath, "utf-8"));
51036
51627
  } catch {
51037
51628
  return null;
51038
51629
  }
51039
51630
  }
51040
51631
  function saveToolProfile(repoRoot, profile) {
51041
- const contextDir = join59(repoRoot, OA_DIR, "context");
51042
- mkdirSync18(contextDir, { recursive: true });
51043
- writeFileSync19(join59(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
51632
+ const contextDir = join60(repoRoot, OA_DIR, "context");
51633
+ mkdirSync19(contextDir, { recursive: true });
51634
+ writeFileSync20(join60(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
51044
51635
  }
51045
51636
  function categorizeToolCall(toolName) {
51046
51637
  for (const cat of TOOL_CATEGORIES) {
@@ -51098,25 +51689,25 @@ function weightedColor(profile) {
51098
51689
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
51099
51690
  }
51100
51691
  function loadCachedDescriptors(repoRoot) {
51101
- const filePath = join59(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
51692
+ const filePath = join60(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
51102
51693
  try {
51103
- if (!existsSync43(filePath))
51694
+ if (!existsSync44(filePath))
51104
51695
  return null;
51105
- const cached = JSON.parse(readFileSync32(filePath, "utf-8"));
51696
+ const cached = JSON.parse(readFileSync33(filePath, "utf-8"));
51106
51697
  return cached.phrases.length > 0 ? cached.phrases : null;
51107
51698
  } catch {
51108
51699
  return null;
51109
51700
  }
51110
51701
  }
51111
51702
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
51112
- const contextDir = join59(repoRoot, OA_DIR, "context");
51113
- mkdirSync18(contextDir, { recursive: true });
51703
+ const contextDir = join60(repoRoot, OA_DIR, "context");
51704
+ mkdirSync19(contextDir, { recursive: true });
51114
51705
  const cached = {
51115
51706
  phrases,
51116
51707
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
51117
51708
  sourceHash
51118
51709
  };
51119
- writeFileSync19(join59(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
51710
+ writeFileSync20(join60(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
51120
51711
  }
51121
51712
  function generateDescriptors(repoRoot) {
51122
51713
  const profile = loadToolProfile(repoRoot);
@@ -51164,11 +51755,11 @@ function generateDescriptors(repoRoot) {
51164
51755
  return phrases;
51165
51756
  }
51166
51757
  function extractFromPackageJson(repoRoot, tags) {
51167
- const pkgPath = join59(repoRoot, "package.json");
51758
+ const pkgPath = join60(repoRoot, "package.json");
51168
51759
  try {
51169
- if (!existsSync43(pkgPath))
51760
+ if (!existsSync44(pkgPath))
51170
51761
  return;
51171
- const pkg = JSON.parse(readFileSync32(pkgPath, "utf-8"));
51762
+ const pkg = JSON.parse(readFileSync33(pkgPath, "utf-8"));
51172
51763
  if (pkg.name && typeof pkg.name === "string") {
51173
51764
  const parts = pkg.name.replace(/^@/, "").split("/");
51174
51765
  for (const p of parts)
@@ -51212,7 +51803,7 @@ function extractFromManifests(repoRoot, tags) {
51212
51803
  { file: ".github/workflows", tag: "ci/cd" }
51213
51804
  ];
51214
51805
  for (const check of manifestChecks) {
51215
- if (existsSync43(join59(repoRoot, check.file))) {
51806
+ if (existsSync44(join60(repoRoot, check.file))) {
51216
51807
  tags.push(check.tag);
51217
51808
  }
51218
51809
  }
@@ -51234,16 +51825,16 @@ function extractFromSessions(repoRoot, tags) {
51234
51825
  }
51235
51826
  }
51236
51827
  function extractFromMemory(repoRoot, tags) {
51237
- const memoryDir = join59(repoRoot, OA_DIR, "memory");
51828
+ const memoryDir = join60(repoRoot, OA_DIR, "memory");
51238
51829
  try {
51239
- if (!existsSync43(memoryDir))
51830
+ if (!existsSync44(memoryDir))
51240
51831
  return;
51241
51832
  const files = readdirSync14(memoryDir).filter((f) => f.endsWith(".json"));
51242
51833
  for (const file of files) {
51243
51834
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
51244
51835
  tags.push(topic);
51245
51836
  try {
51246
- const data = JSON.parse(readFileSync32(join59(memoryDir, file), "utf-8"));
51837
+ const data = JSON.parse(readFileSync33(join60(memoryDir, file), "utf-8"));
51247
51838
  if (data && typeof data === "object") {
51248
51839
  const keys = Object.keys(data).slice(0, 3);
51249
51840
  for (const key of keys) {
@@ -51898,13 +52489,13 @@ var init_stream_renderer = __esm({
51898
52489
  });
51899
52490
 
51900
52491
  // packages/cli/dist/tui/edit-history.js
51901
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync19 } from "node:fs";
51902
- import { join as join60 } from "node:path";
52492
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync20 } from "node:fs";
52493
+ import { join as join61 } from "node:path";
51903
52494
  function createEditHistoryLogger(repoRoot, sessionId) {
51904
- const historyDir = join60(repoRoot, ".oa", "history");
51905
- const logPath2 = join60(historyDir, "edits.jsonl");
52495
+ const historyDir = join61(repoRoot, ".oa", "history");
52496
+ const logPath2 = join61(historyDir, "edits.jsonl");
51906
52497
  try {
51907
- mkdirSync19(historyDir, { recursive: true });
52498
+ mkdirSync20(historyDir, { recursive: true });
51908
52499
  } catch {
51909
52500
  }
51910
52501
  function logToolCall(toolName, toolArgs, success) {
@@ -52013,17 +52604,17 @@ var init_edit_history = __esm({
52013
52604
  });
52014
52605
 
52015
52606
  // packages/cli/dist/tui/promptLoader.js
52016
- import { readFileSync as readFileSync33, existsSync as existsSync44 } from "node:fs";
52017
- import { join as join61, dirname as dirname19 } from "node:path";
52607
+ import { readFileSync as readFileSync34, existsSync as existsSync45 } from "node:fs";
52608
+ import { join as join62, dirname as dirname19 } from "node:path";
52018
52609
  import { fileURLToPath as fileURLToPath11 } from "node:url";
52019
52610
  function loadPrompt3(promptPath, vars) {
52020
52611
  let content = cache3.get(promptPath);
52021
52612
  if (content === void 0) {
52022
- const fullPath = join61(PROMPTS_DIR3, promptPath);
52023
- if (!existsSync44(fullPath)) {
52613
+ const fullPath = join62(PROMPTS_DIR3, promptPath);
52614
+ if (!existsSync45(fullPath)) {
52024
52615
  throw new Error(`Prompt file not found: ${fullPath}`);
52025
52616
  }
52026
- content = readFileSync33(fullPath, "utf-8");
52617
+ content = readFileSync34(fullPath, "utf-8");
52027
52618
  cache3.set(promptPath, content);
52028
52619
  }
52029
52620
  if (!vars)
@@ -52036,23 +52627,23 @@ var init_promptLoader3 = __esm({
52036
52627
  "use strict";
52037
52628
  __filename3 = fileURLToPath11(import.meta.url);
52038
52629
  __dirname6 = dirname19(__filename3);
52039
- devPath2 = join61(__dirname6, "..", "..", "prompts");
52040
- publishedPath2 = join61(__dirname6, "..", "prompts");
52041
- PROMPTS_DIR3 = existsSync44(devPath2) ? devPath2 : publishedPath2;
52630
+ devPath2 = join62(__dirname6, "..", "..", "prompts");
52631
+ publishedPath2 = join62(__dirname6, "..", "prompts");
52632
+ PROMPTS_DIR3 = existsSync45(devPath2) ? devPath2 : publishedPath2;
52042
52633
  cache3 = /* @__PURE__ */ new Map();
52043
52634
  }
52044
52635
  });
52045
52636
 
52046
52637
  // packages/cli/dist/tui/dream-engine.js
52047
- import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync20, readFileSync as readFileSync34, existsSync as existsSync45, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
52048
- import { join as join62, basename as basename14 } from "node:path";
52638
+ import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync21, readFileSync as readFileSync35, existsSync as existsSync46, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
52639
+ import { join as join63, basename as basename14 } from "node:path";
52049
52640
  import { execSync as execSync31 } from "node:child_process";
52050
52641
  function loadAutoresearchMemory(repoRoot) {
52051
- const memoryPath = join62(repoRoot, ".oa", "memory", "autoresearch.json");
52052
- if (!existsSync45(memoryPath))
52642
+ const memoryPath = join63(repoRoot, ".oa", "memory", "autoresearch.json");
52643
+ if (!existsSync46(memoryPath))
52053
52644
  return "";
52054
52645
  try {
52055
- const raw = readFileSync34(memoryPath, "utf-8");
52646
+ const raw = readFileSync35(memoryPath, "utf-8");
52056
52647
  const data = JSON.parse(raw);
52057
52648
  const sections = [];
52058
52649
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -52242,14 +52833,14 @@ var init_dream_engine = __esm({
52242
52833
  const content = String(args["content"] ?? "");
52243
52834
  if (!rawPath)
52244
52835
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
52245
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join62(this.autoresearchDir, basename14(rawPath)) : join62(this.autoresearchDir, rawPath);
52836
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join63(this.autoresearchDir, basename14(rawPath)) : join63(this.autoresearchDir, rawPath);
52246
52837
  if (!targetPath.startsWith(this.autoresearchDir)) {
52247
52838
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
52248
52839
  }
52249
52840
  try {
52250
- const dir = join62(targetPath, "..");
52251
- mkdirSync20(dir, { recursive: true });
52252
- writeFileSync20(targetPath, content, "utf-8");
52841
+ const dir = join63(targetPath, "..");
52842
+ mkdirSync21(dir, { recursive: true });
52843
+ writeFileSync21(targetPath, content, "utf-8");
52253
52844
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
52254
52845
  } catch (err) {
52255
52846
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -52277,20 +52868,20 @@ var init_dream_engine = __esm({
52277
52868
  const rawPath = String(args["path"] ?? "");
52278
52869
  const oldStr = String(args["old_string"] ?? "");
52279
52870
  const newStr = String(args["new_string"] ?? "");
52280
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join62(this.autoresearchDir, basename14(rawPath)) : join62(this.autoresearchDir, rawPath);
52871
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join63(this.autoresearchDir, basename14(rawPath)) : join63(this.autoresearchDir, rawPath);
52281
52872
  if (!targetPath.startsWith(this.autoresearchDir)) {
52282
52873
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
52283
52874
  }
52284
52875
  try {
52285
- if (!existsSync45(targetPath)) {
52876
+ if (!existsSync46(targetPath)) {
52286
52877
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
52287
52878
  }
52288
- let content = readFileSync34(targetPath, "utf-8");
52879
+ let content = readFileSync35(targetPath, "utf-8");
52289
52880
  if (!content.includes(oldStr)) {
52290
52881
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
52291
52882
  }
52292
52883
  content = content.replace(oldStr, newStr);
52293
- writeFileSync20(targetPath, content, "utf-8");
52884
+ writeFileSync21(targetPath, content, "utf-8");
52294
52885
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
52295
52886
  } catch (err) {
52296
52887
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -52331,14 +52922,14 @@ var init_dream_engine = __esm({
52331
52922
  const content = String(args["content"] ?? "");
52332
52923
  if (!rawPath)
52333
52924
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
52334
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join62(this.dreamsDir, basename14(rawPath)) : join62(this.dreamsDir, rawPath);
52925
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join63(this.dreamsDir, basename14(rawPath)) : join63(this.dreamsDir, rawPath);
52335
52926
  if (!targetPath.startsWith(this.dreamsDir)) {
52336
52927
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
52337
52928
  }
52338
52929
  try {
52339
- const dir = join62(targetPath, "..");
52340
- mkdirSync20(dir, { recursive: true });
52341
- writeFileSync20(targetPath, content, "utf-8");
52930
+ const dir = join63(targetPath, "..");
52931
+ mkdirSync21(dir, { recursive: true });
52932
+ writeFileSync21(targetPath, content, "utf-8");
52342
52933
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
52343
52934
  } catch (err) {
52344
52935
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -52366,20 +52957,20 @@ var init_dream_engine = __esm({
52366
52957
  const rawPath = String(args["path"] ?? "");
52367
52958
  const oldStr = String(args["old_string"] ?? "");
52368
52959
  const newStr = String(args["new_string"] ?? "");
52369
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join62(this.dreamsDir, basename14(rawPath)) : join62(this.dreamsDir, rawPath);
52960
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join63(this.dreamsDir, basename14(rawPath)) : join63(this.dreamsDir, rawPath);
52370
52961
  if (!targetPath.startsWith(this.dreamsDir)) {
52371
52962
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
52372
52963
  }
52373
52964
  try {
52374
- if (!existsSync45(targetPath)) {
52965
+ if (!existsSync46(targetPath)) {
52375
52966
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
52376
52967
  }
52377
- let content = readFileSync34(targetPath, "utf-8");
52968
+ let content = readFileSync35(targetPath, "utf-8");
52378
52969
  if (!content.includes(oldStr)) {
52379
52970
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
52380
52971
  }
52381
52972
  content = content.replace(oldStr, newStr);
52382
- writeFileSync20(targetPath, content, "utf-8");
52973
+ writeFileSync21(targetPath, content, "utf-8");
52383
52974
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
52384
52975
  } catch (err) {
52385
52976
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -52433,7 +53024,7 @@ var init_dream_engine = __esm({
52433
53024
  constructor(config, repoRoot) {
52434
53025
  this.config = config;
52435
53026
  this.repoRoot = repoRoot;
52436
- this.dreamsDir = join62(repoRoot, ".oa", "dreams");
53027
+ this.dreamsDir = join63(repoRoot, ".oa", "dreams");
52437
53028
  this.state = {
52438
53029
  mode: "default",
52439
53030
  active: false,
@@ -52464,7 +53055,7 @@ var init_dream_engine = __esm({
52464
53055
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
52465
53056
  results: []
52466
53057
  };
52467
- mkdirSync20(this.dreamsDir, { recursive: true });
53058
+ mkdirSync21(this.dreamsDir, { recursive: true });
52468
53059
  this.saveDreamState();
52469
53060
  try {
52470
53061
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -52517,8 +53108,8 @@ ${result.summary}`;
52517
53108
  if (mode !== "default" || cycle === totalCycles) {
52518
53109
  renderDreamContraction(cycle);
52519
53110
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
52520
- const summaryPath = join62(this.dreamsDir, `cycle-${cycle}-summary.md`);
52521
- writeFileSync20(summaryPath, cycleSummary, "utf-8");
53111
+ const summaryPath = join63(this.dreamsDir, `cycle-${cycle}-summary.md`);
53112
+ writeFileSync21(summaryPath, cycleSummary, "utf-8");
52522
53113
  }
52523
53114
  if (mode === "lucid" && !this.abortController.signal.aborted) {
52524
53115
  this.saveVersionCheckpoint(cycle);
@@ -52730,7 +53321,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
52730
53321
  }
52731
53322
  /** Build role-specific tool sets for swarm agents */
52732
53323
  buildSwarmTools(role, _workspace) {
52733
- const autoresearchDir = join62(this.repoRoot, ".oa", "autoresearch");
53324
+ const autoresearchDir = join63(this.repoRoot, ".oa", "autoresearch");
52734
53325
  const taskComplete = this.createSwarmTaskCompleteTool(role);
52735
53326
  switch (role) {
52736
53327
  case "researcher": {
@@ -53094,7 +53685,7 @@ INSTRUCTIONS:
53094
53685
  2. Summarize the key learnings and next steps
53095
53686
 
53096
53687
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
53097
- const reportPath = join62(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
53688
+ const reportPath = join63(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
53098
53689
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
53099
53690
 
53100
53691
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -53116,8 +53707,8 @@ ${summaryResult}
53116
53707
  *Generated by open-agents autoresearch swarm*
53117
53708
  `;
53118
53709
  try {
53119
- mkdirSync20(this.dreamsDir, { recursive: true });
53120
- writeFileSync20(reportPath, report, "utf-8");
53710
+ mkdirSync21(this.dreamsDir, { recursive: true });
53711
+ writeFileSync21(reportPath, report, "utf-8");
53121
53712
  } catch {
53122
53713
  }
53123
53714
  renderSwarmComplete(workspace);
@@ -53183,9 +53774,9 @@ ${summaryResult}
53183
53774
  }
53184
53775
  /** Save workspace backup for lucid mode */
53185
53776
  saveVersionCheckpoint(cycle) {
53186
- const checkpointDir = join62(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
53777
+ const checkpointDir = join63(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
53187
53778
  try {
53188
- mkdirSync20(checkpointDir, { recursive: true });
53779
+ mkdirSync21(checkpointDir, { recursive: true });
53189
53780
  try {
53190
53781
  const gitStatus = execSync31("git status --porcelain", {
53191
53782
  cwd: this.repoRoot,
@@ -53202,10 +53793,10 @@ ${summaryResult}
53202
53793
  encoding: "utf-8",
53203
53794
  timeout: 5e3
53204
53795
  }).trim();
53205
- writeFileSync20(join62(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
53206
- writeFileSync20(join62(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
53207
- writeFileSync20(join62(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
53208
- writeFileSync20(join62(checkpointDir, "checkpoint.json"), JSON.stringify({
53796
+ writeFileSync21(join63(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
53797
+ writeFileSync21(join63(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
53798
+ writeFileSync21(join63(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
53799
+ writeFileSync21(join63(checkpointDir, "checkpoint.json"), JSON.stringify({
53209
53800
  cycle,
53210
53801
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
53211
53802
  gitHash,
@@ -53213,7 +53804,7 @@ ${summaryResult}
53213
53804
  }, null, 2), "utf-8");
53214
53805
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
53215
53806
  } catch {
53216
- writeFileSync20(join62(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
53807
+ writeFileSync21(join63(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
53217
53808
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
53218
53809
  }
53219
53810
  } catch (err) {
@@ -53271,14 +53862,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
53271
53862
  ---
53272
53863
  *Auto-generated by open-agents dream engine*
53273
53864
  `;
53274
- writeFileSync20(join62(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
53865
+ writeFileSync21(join63(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
53275
53866
  } catch {
53276
53867
  }
53277
53868
  }
53278
53869
  /** Save dream state for resume/inspection */
53279
53870
  saveDreamState() {
53280
53871
  try {
53281
- writeFileSync20(join62(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
53872
+ writeFileSync21(join63(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
53282
53873
  } catch {
53283
53874
  }
53284
53875
  }
@@ -53652,8 +54243,8 @@ var init_bless_engine = __esm({
53652
54243
  });
53653
54244
 
53654
54245
  // packages/cli/dist/tui/dmn-engine.js
53655
- import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync21, mkdirSync as mkdirSync21, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
53656
- import { join as join63, basename as basename15 } from "node:path";
54246
+ import { existsSync as existsSync47, readFileSync as readFileSync36, writeFileSync as writeFileSync22, mkdirSync as mkdirSync22, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
54247
+ import { join as join64, basename as basename15 } from "node:path";
53657
54248
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
53658
54249
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
53659
54250
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -53773,9 +54364,9 @@ var init_dmn_engine = __esm({
53773
54364
  constructor(config, repoRoot) {
53774
54365
  this.config = config;
53775
54366
  this.repoRoot = repoRoot;
53776
- this.stateDir = join63(repoRoot, ".oa", "dmn");
53777
- this.historyDir = join63(repoRoot, ".oa", "dmn", "cycles");
53778
- mkdirSync21(this.historyDir, { recursive: true });
54367
+ this.stateDir = join64(repoRoot, ".oa", "dmn");
54368
+ this.historyDir = join64(repoRoot, ".oa", "dmn", "cycles");
54369
+ mkdirSync22(this.historyDir, { recursive: true });
53779
54370
  this.loadState();
53780
54371
  }
53781
54372
  get stats() {
@@ -54364,11 +54955,11 @@ OUTPUT: Call task_complete with JSON:
54364
54955
  async gatherMemoryTopics() {
54365
54956
  const topics = [];
54366
54957
  const dirs = [
54367
- join63(this.repoRoot, ".oa", "memory"),
54368
- join63(this.repoRoot, ".open-agents", "memory")
54958
+ join64(this.repoRoot, ".oa", "memory"),
54959
+ join64(this.repoRoot, ".open-agents", "memory")
54369
54960
  ];
54370
54961
  for (const dir of dirs) {
54371
- if (!existsSync46(dir))
54962
+ if (!existsSync47(dir))
54372
54963
  continue;
54373
54964
  try {
54374
54965
  const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
@@ -54384,29 +54975,29 @@ OUTPUT: Call task_complete with JSON:
54384
54975
  }
54385
54976
  // ── State persistence ─────────────────────────────────────────────────
54386
54977
  loadState() {
54387
- const path = join63(this.stateDir, "state.json");
54388
- if (existsSync46(path)) {
54978
+ const path = join64(this.stateDir, "state.json");
54979
+ if (existsSync47(path)) {
54389
54980
  try {
54390
- this.state = JSON.parse(readFileSync35(path, "utf-8"));
54981
+ this.state = JSON.parse(readFileSync36(path, "utf-8"));
54391
54982
  } catch {
54392
54983
  }
54393
54984
  }
54394
54985
  }
54395
54986
  saveState() {
54396
54987
  try {
54397
- writeFileSync21(join63(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
54988
+ writeFileSync22(join64(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
54398
54989
  } catch {
54399
54990
  }
54400
54991
  }
54401
54992
  saveCycleResult(result) {
54402
54993
  try {
54403
54994
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
54404
- writeFileSync21(join63(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
54995
+ writeFileSync22(join64(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
54405
54996
  const files = readdirSync16(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
54406
54997
  if (files.length > 50) {
54407
54998
  for (const old of files.slice(0, files.length - 50)) {
54408
54999
  try {
54409
- unlinkSync10(join63(this.historyDir, old));
55000
+ unlinkSync10(join64(this.historyDir, old));
54410
55001
  } catch {
54411
55002
  }
54412
55003
  }
@@ -54419,8 +55010,8 @@ OUTPUT: Call task_complete with JSON:
54419
55010
  });
54420
55011
 
54421
55012
  // packages/cli/dist/tui/snr-engine.js
54422
- import { existsSync as existsSync47, readdirSync as readdirSync17, readFileSync as readFileSync36 } from "node:fs";
54423
- import { join as join64, basename as basename16 } from "node:path";
55013
+ import { existsSync as existsSync48, readdirSync as readdirSync17, readFileSync as readFileSync37 } from "node:fs";
55014
+ import { join as join65, basename as basename16 } from "node:path";
54424
55015
  function computeDPrime(signalScores, noiseScores) {
54425
55016
  if (signalScores.length === 0 || noiseScores.length === 0)
54426
55017
  return 0;
@@ -54660,11 +55251,11 @@ Call task_complete with the JSON array when done.`, onEvent)
54660
55251
  loadMemoryEntries(topics) {
54661
55252
  const entries = [];
54662
55253
  const dirs = [
54663
- join64(this.repoRoot, ".oa", "memory"),
54664
- join64(this.repoRoot, ".open-agents", "memory")
55254
+ join65(this.repoRoot, ".oa", "memory"),
55255
+ join65(this.repoRoot, ".open-agents", "memory")
54665
55256
  ];
54666
55257
  for (const dir of dirs) {
54667
- if (!existsSync47(dir))
55258
+ if (!existsSync48(dir))
54668
55259
  continue;
54669
55260
  try {
54670
55261
  const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
@@ -54673,7 +55264,7 @@ Call task_complete with the JSON array when done.`, onEvent)
54673
55264
  if (topics.length > 0 && !topics.includes(topic))
54674
55265
  continue;
54675
55266
  try {
54676
- const data = JSON.parse(readFileSync36(join64(dir, f), "utf-8"));
55267
+ const data = JSON.parse(readFileSync37(join65(dir, f), "utf-8"));
54677
55268
  for (const [key, val] of Object.entries(data)) {
54678
55269
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
54679
55270
  entries.push({ topic, key, value });
@@ -55240,8 +55831,8 @@ var init_tool_policy = __esm({
55240
55831
  });
55241
55832
 
55242
55833
  // packages/cli/dist/tui/telegram-bridge.js
55243
- import { mkdirSync as mkdirSync22, existsSync as existsSync48, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
55244
- import { join as join65, resolve as resolve30 } from "node:path";
55834
+ import { mkdirSync as mkdirSync23, existsSync as existsSync49, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
55835
+ import { join as join66, resolve as resolve30 } from "node:path";
55245
55836
  import { writeFile as writeFileAsync } from "node:fs/promises";
55246
55837
  function convertMarkdownToTelegramHTML(md) {
55247
55838
  let html = md;
@@ -55569,7 +56160,7 @@ with summary "no_reply" to silently skip without responding.
55569
56160
  this.polling = true;
55570
56161
  this.abortController = new AbortController();
55571
56162
  try {
55572
- mkdirSync22(this.mediaCacheDir, { recursive: true });
56163
+ mkdirSync23(this.mediaCacheDir, { recursive: true });
55573
56164
  } catch {
55574
56165
  }
55575
56166
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -56006,7 +56597,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
56006
56597
  return null;
56007
56598
  const buffer = Buffer.from(await res.arrayBuffer());
56008
56599
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
56009
- const localPath = join65(this.mediaCacheDir, fileName);
56600
+ const localPath = join66(this.mediaCacheDir, fileName);
56010
56601
  await writeFileAsync(localPath, buffer);
56011
56602
  return localPath;
56012
56603
  } catch {
@@ -57362,7 +57953,7 @@ var init_text_selection = __esm({
57362
57953
  });
57363
57954
 
57364
57955
  // packages/cli/dist/tui/status-bar.js
57365
- import { readFileSync as readFileSync37 } from "node:fs";
57956
+ import { readFileSync as readFileSync38 } from "node:fs";
57366
57957
  function setTerminalTitle(task, version) {
57367
57958
  if (!process.stdout.isTTY)
57368
57959
  return;
@@ -58044,7 +58635,7 @@ var init_status_bar = __esm({
58044
58635
  if (nexusDir) {
58045
58636
  try {
58046
58637
  const metricsPath = nexusDir + "/remote-metrics.json";
58047
- const raw = readFileSync37(metricsPath, "utf8");
58638
+ const raw = readFileSync38(metricsPath, "utf8");
58048
58639
  const cached = JSON.parse(raw);
58049
58640
  if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
58050
58641
  const m = cached.data;
@@ -59643,11 +60234,11 @@ var init_mouse_filter = __esm({
59643
60234
  import * as readline2 from "node:readline";
59644
60235
  import { Writable } from "node:stream";
59645
60236
  import { cwd } from "node:process";
59646
- import { resolve as resolve31, join as join66, dirname as dirname20, extname as extname11 } from "node:path";
60237
+ import { resolve as resolve31, join as join67, dirname as dirname20, extname as extname11 } from "node:path";
59647
60238
  import { createRequire as createRequire2 } from "node:module";
59648
60239
  import { fileURLToPath as fileURLToPath12 } from "node:url";
59649
- import { readFileSync as readFileSync38, writeFileSync as writeFileSync22, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync19, mkdirSync as mkdirSync23 } from "node:fs";
59650
- import { existsSync as existsSync49 } from "node:fs";
60240
+ import { readFileSync as readFileSync39, writeFileSync as writeFileSync23, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync19, mkdirSync as mkdirSync24 } from "node:fs";
60241
+ import { existsSync as existsSync50 } from "node:fs";
59651
60242
  import { execSync as execSync33 } from "node:child_process";
59652
60243
  import { homedir as homedir16 } from "node:os";
59653
60244
  function formatTimeAgo(date) {
@@ -59668,12 +60259,12 @@ function getVersion3() {
59668
60259
  const require2 = createRequire2(import.meta.url);
59669
60260
  const thisDir = dirname20(fileURLToPath12(import.meta.url));
59670
60261
  const candidates = [
59671
- join66(thisDir, "..", "package.json"),
59672
- join66(thisDir, "..", "..", "package.json"),
59673
- join66(thisDir, "..", "..", "..", "package.json")
60262
+ join67(thisDir, "..", "package.json"),
60263
+ join67(thisDir, "..", "..", "package.json"),
60264
+ join67(thisDir, "..", "..", "..", "package.json")
59674
60265
  ];
59675
60266
  for (const pkgPath of candidates) {
59676
- if (existsSync49(pkgPath)) {
60267
+ if (existsSync50(pkgPath)) {
59677
60268
  const pkg = require2(pkgPath);
59678
60269
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
59679
60270
  return pkg.version ?? "0.0.0";
@@ -59908,15 +60499,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
59908
60499
  function gatherMemorySnippets(root) {
59909
60500
  const snippets = [];
59910
60501
  const dirs = [
59911
- join66(root, ".oa", "memory"),
59912
- join66(root, ".open-agents", "memory")
60502
+ join67(root, ".oa", "memory"),
60503
+ join67(root, ".open-agents", "memory")
59913
60504
  ];
59914
60505
  for (const dir of dirs) {
59915
- if (!existsSync49(dir))
60506
+ if (!existsSync50(dir))
59916
60507
  continue;
59917
60508
  try {
59918
60509
  for (const f of readdirSync19(dir).filter((f2) => f2.endsWith(".json"))) {
59919
- const data = JSON.parse(readFileSync38(join66(dir, f), "utf-8"));
60510
+ const data = JSON.parse(readFileSync39(join67(dir, f), "utf-8"));
59920
60511
  for (const val of Object.values(data)) {
59921
60512
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
59922
60513
  if (v.length > 10)
@@ -60073,9 +60664,9 @@ ${metabolismMemories}
60073
60664
  } catch {
60074
60665
  }
60075
60666
  try {
60076
- const archeFile = join66(repoRoot, ".oa", "arche", "variants.json");
60077
- if (existsSync49(archeFile)) {
60078
- const variants = JSON.parse(readFileSync38(archeFile, "utf8"));
60667
+ const archeFile = join67(repoRoot, ".oa", "arche", "variants.json");
60668
+ if (existsSync50(archeFile)) {
60669
+ const variants = JSON.parse(readFileSync39(archeFile, "utf8"));
60079
60670
  if (variants.length > 0) {
60080
60671
  let filtered = variants;
60081
60672
  if (taskType) {
@@ -60212,9 +60803,9 @@ ${lines.join("\n")}
60212
60803
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
60213
60804
  let identityInjection = "";
60214
60805
  try {
60215
- const ikStateFile = join66(repoRoot, ".oa", "identity", "self-state.json");
60216
- if (existsSync49(ikStateFile)) {
60217
- const selfState = JSON.parse(readFileSync38(ikStateFile, "utf8"));
60806
+ const ikStateFile = join67(repoRoot, ".oa", "identity", "self-state.json");
60807
+ if (existsSync50(ikStateFile)) {
60808
+ const selfState = JSON.parse(readFileSync39(ikStateFile, "utf8"));
60218
60809
  const lines = [
60219
60810
  `[Identity State v${selfState.version}]`,
60220
60811
  `Self: ${selfState.narrative_summary}`,
@@ -60855,13 +61446,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
60855
61446
  });
60856
61447
  }
60857
61448
  try {
60858
- const ikDir = join66(repoRoot, ".oa", "identity");
60859
- const ikFile = join66(ikDir, "self-state.json");
61449
+ const ikDir = join67(repoRoot, ".oa", "identity");
61450
+ const ikFile = join67(ikDir, "self-state.json");
60860
61451
  let ikState;
60861
- if (existsSync49(ikFile)) {
60862
- ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
61452
+ if (existsSync50(ikFile)) {
61453
+ ikState = JSON.parse(readFileSync39(ikFile, "utf8"));
60863
61454
  } else {
60864
- mkdirSync23(ikDir, { recursive: true });
61455
+ mkdirSync24(ikDir, { recursive: true });
60865
61456
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
60866
61457
  ikState = {
60867
61458
  self_id: `oa-${machineId}`,
@@ -60887,7 +61478,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
60887
61478
  }
60888
61479
  ikState.session_count = (ikState.session_count || 0) + 1;
60889
61480
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
60890
- writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
61481
+ writeFileSync23(ikFile, JSON.stringify(ikState, null, 2));
60891
61482
  } catch (ikErr) {
60892
61483
  try {
60893
61484
  console.error("[IK-OBSERVE]", ikErr);
@@ -60902,14 +61493,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
60902
61493
  } else {
60903
61494
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
60904
61495
  try {
60905
- const ikFile = join66(repoRoot, ".oa", "identity", "self-state.json");
60906
- if (existsSync49(ikFile)) {
60907
- const ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
61496
+ const ikFile = join67(repoRoot, ".oa", "identity", "self-state.json");
61497
+ if (existsSync50(ikFile)) {
61498
+ const ikState = JSON.parse(readFileSync39(ikFile, "utf8"));
60908
61499
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
60909
61500
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
60910
61501
  ikState.session_count = (ikState.session_count || 0) + 1;
60911
61502
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
60912
- writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
61503
+ writeFileSync23(ikFile, JSON.stringify(ikState, null, 2));
60913
61504
  }
60914
61505
  } catch {
60915
61506
  }
@@ -61252,7 +61843,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
61252
61843
  let p2pGateway = null;
61253
61844
  let peerMesh = null;
61254
61845
  let inferenceRouter = null;
61255
- const secretVault = new SecretVault(join66(repoRoot, ".oa", "vault.enc"));
61846
+ const secretVault = new SecretVault(join67(repoRoot, ".oa", "vault.enc"));
61256
61847
  let adminSessionKey = null;
61257
61848
  const callSubAgents = /* @__PURE__ */ new Map();
61258
61849
  const streamRenderer = new StreamRenderer();
@@ -61437,6 +62028,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
61437
62028
  "/p2p",
61438
62029
  "/secrets",
61439
62030
  "/vault",
62031
+ "/sponsor",
61440
62032
  "/full-send-bless",
61441
62033
  "/bless",
61442
62034
  "/telegram",
@@ -61472,13 +62064,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
61472
62064
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
61473
62065
  return [hits, line];
61474
62066
  }
61475
- const HISTORY_DIR = join66(homedir16(), ".open-agents");
61476
- const HISTORY_FILE = join66(HISTORY_DIR, "repl-history");
62067
+ const HISTORY_DIR = join67(homedir16(), ".open-agents");
62068
+ const HISTORY_FILE = join67(HISTORY_DIR, "repl-history");
61477
62069
  const MAX_HISTORY_LINES = 500;
61478
62070
  let savedHistory = [];
61479
62071
  try {
61480
- if (existsSync49(HISTORY_FILE)) {
61481
- const raw = readFileSync38(HISTORY_FILE, "utf8").trim();
62072
+ if (existsSync50(HISTORY_FILE)) {
62073
+ const raw = readFileSync39(HISTORY_FILE, "utf8").trim();
61482
62074
  if (raw)
61483
62075
  savedHistory = raw.split("\n").reverse();
61484
62076
  }
@@ -61558,12 +62150,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
61558
62150
  if (!line.trim())
61559
62151
  return;
61560
62152
  try {
61561
- mkdirSync23(HISTORY_DIR, { recursive: true });
62153
+ mkdirSync24(HISTORY_DIR, { recursive: true });
61562
62154
  appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
61563
62155
  if (Math.random() < 0.02) {
61564
- const all = readFileSync38(HISTORY_FILE, "utf8").trim().split("\n");
62156
+ const all = readFileSync39(HISTORY_FILE, "utf8").trim().split("\n");
61565
62157
  if (all.length > MAX_HISTORY_LINES) {
61566
- writeFileSync22(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
62158
+ writeFileSync23(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
61567
62159
  }
61568
62160
  }
61569
62161
  } catch {
@@ -61739,7 +62331,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
61739
62331
  } catch {
61740
62332
  }
61741
62333
  try {
61742
- const oaDir = join66(repoRoot, ".oa");
62334
+ const oaDir = join67(repoRoot, ".oa");
61743
62335
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
61744
62336
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
61745
62337
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -61762,7 +62354,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
61762
62354
  } catch {
61763
62355
  }
61764
62356
  try {
61765
- const oaDir = join66(repoRoot, ".oa");
62357
+ const oaDir = join67(repoRoot, ".oa");
61766
62358
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
61767
62359
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
61768
62360
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -62646,7 +63238,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
62646
63238
  kind,
62647
63239
  targetUrl,
62648
63240
  authKey,
62649
- stateDir: join66(repoRoot, ".oa"),
63241
+ stateDir: join67(repoRoot, ".oa"),
62650
63242
  passthrough: passthrough ?? false,
62651
63243
  loadbalance: loadbalance ?? false,
62652
63244
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -62694,7 +63286,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
62694
63286
  await tunnelGateway.stop();
62695
63287
  tunnelGateway = null;
62696
63288
  }
62697
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join66(repoRoot, ".oa") });
63289
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join67(repoRoot, ".oa") });
62698
63290
  newTunnel.on("stats", (stats) => {
62699
63291
  statusBar.setExposeStatus({
62700
63292
  status: stats.status,
@@ -62963,10 +63555,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
62963
63555
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
62964
63556
  }
62965
63557
  try {
62966
- const nexusDir = join66(repoRoot, OA_DIR, "nexus");
62967
- const pidFile = join66(nexusDir, "daemon.pid");
62968
- if (existsSync49(pidFile)) {
62969
- const pid = parseInt(readFileSync38(pidFile, "utf8").trim(), 10);
63558
+ const nexusDir = join67(repoRoot, OA_DIR, "nexus");
63559
+ const pidFile = join67(nexusDir, "daemon.pid");
63560
+ if (existsSync50(pidFile)) {
63561
+ const pid = parseInt(readFileSync39(pidFile, "utf8").trim(), 10);
62970
63562
  if (pid > 0) {
62971
63563
  try {
62972
63564
  if (process.platform === "win32") {
@@ -62988,13 +63580,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
62988
63580
  } catch {
62989
63581
  }
62990
63582
  try {
62991
- const voiceDir2 = join66(homedir16(), ".open-agents", "voice");
63583
+ const voiceDir2 = join67(homedir16(), ".open-agents", "voice");
62992
63584
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
62993
63585
  for (const pf of voicePidFiles) {
62994
- const pidPath = join66(voiceDir2, pf);
62995
- if (existsSync49(pidPath)) {
63586
+ const pidPath = join67(voiceDir2, pf);
63587
+ if (existsSync50(pidPath)) {
62996
63588
  try {
62997
- const pid = parseInt(readFileSync38(pidPath, "utf8").trim(), 10);
63589
+ const pid = parseInt(readFileSync39(pidPath, "utf8").trim(), 10);
62998
63590
  if (pid > 0) {
62999
63591
  if (process.platform === "win32") {
63000
63592
  try {
@@ -63018,8 +63610,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
63018
63610
  execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
63019
63611
  } catch {
63020
63612
  }
63021
- const oaPath = join66(repoRoot, OA_DIR);
63022
- if (existsSync49(oaPath)) {
63613
+ const oaPath = join67(repoRoot, OA_DIR);
63614
+ if (existsSync50(oaPath)) {
63023
63615
  let deleted = false;
63024
63616
  for (let attempt = 0; attempt < 3; attempt++) {
63025
63617
  try {
@@ -63391,8 +63983,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
63391
63983
  }
63392
63984
  }
63393
63985
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
63394
- const isImage = isImagePath(cleanPath) && existsSync49(resolve31(repoRoot, cleanPath));
63395
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync49(resolve31(repoRoot, cleanPath));
63986
+ const isImage = isImagePath(cleanPath) && existsSync50(resolve31(repoRoot, cleanPath));
63987
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync50(resolve31(repoRoot, cleanPath));
63396
63988
  if (activeTask) {
63397
63989
  if (activeTask.runner.isPaused) {
63398
63990
  activeTask.runner.resume();
@@ -63401,7 +63993,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
63401
63993
  if (isImage) {
63402
63994
  try {
63403
63995
  const imgPath = resolve31(repoRoot, cleanPath);
63404
- const imgBuffer = readFileSync38(imgPath);
63996
+ const imgBuffer = readFileSync39(imgPath);
63405
63997
  const base64 = imgBuffer.toString("base64");
63406
63998
  const ext = extname11(cleanPath).toLowerCase();
63407
63999
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -63900,13 +64492,13 @@ async function runWithTUI(task, config, repoPath) {
63900
64492
  const handle = startTask(task, config, repoRoot);
63901
64493
  await handle.promise;
63902
64494
  try {
63903
- const ikDir = join66(repoRoot, ".oa", "identity");
63904
- const ikFile = join66(ikDir, "self-state.json");
64495
+ const ikDir = join67(repoRoot, ".oa", "identity");
64496
+ const ikFile = join67(ikDir, "self-state.json");
63905
64497
  let ikState;
63906
- if (existsSync49(ikFile)) {
63907
- ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
64498
+ if (existsSync50(ikFile)) {
64499
+ ikState = JSON.parse(readFileSync39(ikFile, "utf8"));
63908
64500
  } else {
63909
- mkdirSync23(ikDir, { recursive: true });
64501
+ mkdirSync24(ikDir, { recursive: true });
63910
64502
  ikState = {
63911
64503
  self_id: `oa-${Date.now().toString(36)}`,
63912
64504
  version: 1,
@@ -63928,7 +64520,7 @@ async function runWithTUI(task, config, repoPath) {
63928
64520
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
63929
64521
  ikState.session_count = (ikState.session_count || 0) + 1;
63930
64522
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
63931
- writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
64523
+ writeFileSync23(ikFile, JSON.stringify(ikState, null, 2));
63932
64524
  } catch (ikErr) {
63933
64525
  }
63934
64526
  try {
@@ -63937,12 +64529,12 @@ async function runWithTUI(task, config, repoPath) {
63937
64529
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
63938
64530
  } catch {
63939
64531
  try {
63940
- const archeDir = join66(repoRoot, ".oa", "arche");
63941
- const archeFile = join66(archeDir, "variants.json");
64532
+ const archeDir = join67(repoRoot, ".oa", "arche");
64533
+ const archeFile = join67(archeDir, "variants.json");
63942
64534
  let variants = [];
63943
64535
  try {
63944
- if (existsSync49(archeFile))
63945
- variants = JSON.parse(readFileSync38(archeFile, "utf8"));
64536
+ if (existsSync50(archeFile))
64537
+ variants = JSON.parse(readFileSync39(archeFile, "utf8"));
63946
64538
  } catch {
63947
64539
  }
63948
64540
  variants.push({
@@ -63957,15 +64549,15 @@ async function runWithTUI(task, config, repoPath) {
63957
64549
  });
63958
64550
  if (variants.length > 50)
63959
64551
  variants = variants.slice(-50);
63960
- mkdirSync23(archeDir, { recursive: true });
63961
- writeFileSync22(archeFile, JSON.stringify(variants, null, 2));
64552
+ mkdirSync24(archeDir, { recursive: true });
64553
+ writeFileSync23(archeFile, JSON.stringify(variants, null, 2));
63962
64554
  } catch {
63963
64555
  }
63964
64556
  }
63965
64557
  try {
63966
- const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
63967
- if (existsSync49(metaFile)) {
63968
- const store = JSON.parse(readFileSync38(metaFile, "utf8"));
64558
+ const metaFile = join67(repoRoot, ".oa", "memory", "metabolism", "store.json");
64559
+ if (existsSync50(metaFile)) {
64560
+ const store = JSON.parse(readFileSync39(metaFile, "utf8"));
63969
64561
  const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
63970
64562
  let updated = false;
63971
64563
  for (const item of surfaced) {
@@ -63976,7 +64568,7 @@ async function runWithTUI(task, config, repoPath) {
63976
64568
  updated = true;
63977
64569
  }
63978
64570
  if (updated) {
63979
- writeFileSync22(metaFile, JSON.stringify(store, null, 2));
64571
+ writeFileSync23(metaFile, JSON.stringify(store, null, 2));
63980
64572
  }
63981
64573
  }
63982
64574
  } catch {
@@ -64029,9 +64621,9 @@ Rules:
64029
64621
  try {
64030
64622
  const { initDb: initDb2 } = __require("@open-agents/memory");
64031
64623
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
64032
- const dbDir = join66(repoRoot, ".oa", "memory");
64033
- mkdirSync23(dbDir, { recursive: true });
64034
- const db = initDb2(join66(dbDir, "structured.db"));
64624
+ const dbDir = join67(repoRoot, ".oa", "memory");
64625
+ mkdirSync24(dbDir, { recursive: true });
64626
+ const db = initDb2(join67(dbDir, "structured.db"));
64035
64627
  const memStore = new ProceduralMemoryStore2(db);
64036
64628
  memStore.createWithEmbedding({
64037
64629
  content: content.slice(0, 600),
@@ -64046,12 +64638,12 @@ Rules:
64046
64638
  db.close();
64047
64639
  } catch {
64048
64640
  }
64049
- const metaDir = join66(repoRoot, ".oa", "memory", "metabolism");
64050
- const storeFile = join66(metaDir, "store.json");
64641
+ const metaDir = join67(repoRoot, ".oa", "memory", "metabolism");
64642
+ const storeFile = join67(metaDir, "store.json");
64051
64643
  let store = [];
64052
64644
  try {
64053
- if (existsSync49(storeFile))
64054
- store = JSON.parse(readFileSync38(storeFile, "utf8"));
64645
+ if (existsSync50(storeFile))
64646
+ store = JSON.parse(readFileSync39(storeFile, "utf8"));
64055
64647
  } catch {
64056
64648
  }
64057
64649
  store.push({
@@ -64067,26 +64659,26 @@ Rules:
64067
64659
  });
64068
64660
  if (store.length > 100)
64069
64661
  store = store.slice(-100);
64070
- mkdirSync23(metaDir, { recursive: true });
64071
- writeFileSync22(storeFile, JSON.stringify(store, null, 2));
64662
+ mkdirSync24(metaDir, { recursive: true });
64663
+ writeFileSync23(storeFile, JSON.stringify(store, null, 2));
64072
64664
  }
64073
64665
  }
64074
64666
  } catch {
64075
64667
  }
64076
64668
  try {
64077
- const cohereSettingsFile = join66(repoRoot, ".oa", "settings.json");
64669
+ const cohereSettingsFile = join67(repoRoot, ".oa", "settings.json");
64078
64670
  let cohereActive = false;
64079
64671
  try {
64080
- if (existsSync49(cohereSettingsFile)) {
64081
- const settings = JSON.parse(readFileSync38(cohereSettingsFile, "utf8"));
64672
+ if (existsSync50(cohereSettingsFile)) {
64673
+ const settings = JSON.parse(readFileSync39(cohereSettingsFile, "utf8"));
64082
64674
  cohereActive = settings.cohere === true;
64083
64675
  }
64084
64676
  } catch {
64085
64677
  }
64086
64678
  if (cohereActive) {
64087
- const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
64088
- if (existsSync49(metaFile)) {
64089
- const store = JSON.parse(readFileSync38(metaFile, "utf8"));
64679
+ const metaFile = join67(repoRoot, ".oa", "memory", "metabolism", "store.json");
64680
+ if (existsSync50(metaFile)) {
64681
+ const store = JSON.parse(readFileSync39(metaFile, "utf8"));
64090
64682
  const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
64091
64683
  if (latest && latest.scores?.confidence >= 0.6) {
64092
64684
  try {
@@ -64111,18 +64703,18 @@ Rules:
64111
64703
  }
64112
64704
  } catch (err) {
64113
64705
  try {
64114
- const ikFile = join66(repoRoot, ".oa", "identity", "self-state.json");
64115
- if (existsSync49(ikFile)) {
64116
- const ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
64706
+ const ikFile = join67(repoRoot, ".oa", "identity", "self-state.json");
64707
+ if (existsSync50(ikFile)) {
64708
+ const ikState = JSON.parse(readFileSync39(ikFile, "utf8"));
64117
64709
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
64118
64710
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
64119
64711
  ikState.session_count = (ikState.session_count || 0) + 1;
64120
64712
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
64121
- writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
64713
+ writeFileSync23(ikFile, JSON.stringify(ikState, null, 2));
64122
64714
  }
64123
- const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
64124
- if (existsSync49(metaFile)) {
64125
- const store = JSON.parse(readFileSync38(metaFile, "utf8"));
64715
+ const metaFile = join67(repoRoot, ".oa", "memory", "metabolism", "store.json");
64716
+ if (existsSync50(metaFile)) {
64717
+ const store = JSON.parse(readFileSync39(metaFile, "utf8"));
64126
64718
  const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
64127
64719
  for (const item of surfaced) {
64128
64720
  item.accessCount = (item.accessCount || 0) + 1;
@@ -64130,15 +64722,15 @@ Rules:
64130
64722
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
64131
64723
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
64132
64724
  }
64133
- writeFileSync22(metaFile, JSON.stringify(store, null, 2));
64725
+ writeFileSync23(metaFile, JSON.stringify(store, null, 2));
64134
64726
  }
64135
64727
  try {
64136
- const archeDir = join66(repoRoot, ".oa", "arche");
64137
- const archeFile = join66(archeDir, "variants.json");
64728
+ const archeDir = join67(repoRoot, ".oa", "arche");
64729
+ const archeFile = join67(archeDir, "variants.json");
64138
64730
  let variants = [];
64139
64731
  try {
64140
- if (existsSync49(archeFile))
64141
- variants = JSON.parse(readFileSync38(archeFile, "utf8"));
64732
+ if (existsSync50(archeFile))
64733
+ variants = JSON.parse(readFileSync39(archeFile, "utf8"));
64142
64734
  } catch {
64143
64735
  }
64144
64736
  variants.push({
@@ -64153,8 +64745,8 @@ Rules:
64153
64745
  });
64154
64746
  if (variants.length > 50)
64155
64747
  variants = variants.slice(-50);
64156
- mkdirSync23(archeDir, { recursive: true });
64157
- writeFileSync22(archeFile, JSON.stringify(variants, null, 2));
64748
+ mkdirSync24(archeDir, { recursive: true });
64749
+ writeFileSync23(archeFile, JSON.stringify(variants, null, 2));
64158
64750
  } catch {
64159
64751
  }
64160
64752
  } catch {
@@ -64221,13 +64813,13 @@ __export(run_exports, {
64221
64813
  });
64222
64814
  import { resolve as resolve32 } from "node:path";
64223
64815
  import { spawn as spawn20 } from "node:child_process";
64224
- import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, readFileSync as readFileSync39, readdirSync as readdirSync20, existsSync as existsSync50 } from "node:fs";
64816
+ import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync24, readFileSync as readFileSync40, readdirSync as readdirSync20, existsSync as existsSync51 } from "node:fs";
64225
64817
  import { randomBytes as randomBytes15 } from "node:crypto";
64226
- import { join as join67 } from "node:path";
64818
+ import { join as join68 } from "node:path";
64227
64819
  function jobsDir(repoPath) {
64228
64820
  const root = resolve32(repoPath ?? process.cwd());
64229
- const dir = join67(root, ".oa", "jobs");
64230
- mkdirSync24(dir, { recursive: true });
64821
+ const dir = join68(root, ".oa", "jobs");
64822
+ mkdirSync25(dir, { recursive: true });
64231
64823
  return dir;
64232
64824
  }
64233
64825
  async function runCommand(opts, config) {
@@ -64312,7 +64904,7 @@ async function runBackground(task, config, opts) {
64312
64904
  });
64313
64905
  child.unref();
64314
64906
  job.pid = child.pid ?? 0;
64315
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
64907
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
64316
64908
  let output = "";
64317
64909
  child.stdout?.on("data", (chunk) => {
64318
64910
  output += chunk.toString();
@@ -64328,7 +64920,7 @@ async function runBackground(task, config, opts) {
64328
64920
  job.summary = result.summary;
64329
64921
  job.durationMs = result.durationMs;
64330
64922
  job.error = result.error;
64331
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
64923
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
64332
64924
  } catch {
64333
64925
  }
64334
64926
  });
@@ -64344,13 +64936,13 @@ async function runBackground(task, config, opts) {
64344
64936
  }
64345
64937
  function statusCommand(jobId, repoPath) {
64346
64938
  const dir = jobsDir(repoPath);
64347
- const file = join67(dir, `${jobId}.json`);
64348
- if (!existsSync50(file)) {
64939
+ const file = join68(dir, `${jobId}.json`);
64940
+ if (!existsSync51(file)) {
64349
64941
  console.error(`Job not found: ${jobId}`);
64350
64942
  console.log(`Available jobs: oa jobs`);
64351
64943
  process.exit(1);
64352
64944
  }
64353
- const job = JSON.parse(readFileSync39(file, "utf-8"));
64945
+ const job = JSON.parse(readFileSync40(file, "utf-8"));
64354
64946
  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`;
64355
64947
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
64356
64948
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -64373,7 +64965,7 @@ function jobsCommand(repoPath) {
64373
64965
  console.log("Jobs:");
64374
64966
  for (const file of files) {
64375
64967
  try {
64376
- const job = JSON.parse(readFileSync39(join67(dir, file), "utf-8"));
64968
+ const job = JSON.parse(readFileSync40(join68(dir, file), "utf-8"));
64377
64969
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
64378
64970
  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`;
64379
64971
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -64393,7 +64985,7 @@ import { glob } from "glob";
64393
64985
  import ignore from "ignore";
64394
64986
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
64395
64987
  import { createHash as createHash5 } from "node:crypto";
64396
- import { join as join68, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
64988
+ import { join as join69, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
64397
64989
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
64398
64990
  var init_codebase_indexer = __esm({
64399
64991
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -64437,7 +65029,7 @@ var init_codebase_indexer = __esm({
64437
65029
  const ig = ignore.default();
64438
65030
  if (this.config.respectGitignore) {
64439
65031
  try {
64440
- const gitignoreContent = await readFile23(join68(this.config.rootDir, ".gitignore"), "utf-8");
65032
+ const gitignoreContent = await readFile23(join69(this.config.rootDir, ".gitignore"), "utf-8");
64441
65033
  ig.add(gitignoreContent);
64442
65034
  } catch {
64443
65035
  }
@@ -64452,7 +65044,7 @@ var init_codebase_indexer = __esm({
64452
65044
  for (const relativePath of files) {
64453
65045
  if (ig.ignores(relativePath))
64454
65046
  continue;
64455
- const fullPath = join68(this.config.rootDir, relativePath);
65047
+ const fullPath = join69(this.config.rootDir, relativePath);
64456
65048
  try {
64457
65049
  const fileStat = await stat4(fullPath);
64458
65050
  if (fileStat.size > this.config.maxFileSize)
@@ -64498,7 +65090,7 @@ var init_codebase_indexer = __esm({
64498
65090
  if (!child) {
64499
65091
  child = {
64500
65092
  name: part,
64501
- path: join68(current.path, part),
65093
+ path: join69(current.path, part),
64502
65094
  type: "directory",
64503
65095
  children: []
64504
65096
  };
@@ -64581,13 +65173,13 @@ __export(index_repo_exports, {
64581
65173
  indexRepoCommand: () => indexRepoCommand
64582
65174
  });
64583
65175
  import { resolve as resolve33 } from "node:path";
64584
- import { existsSync as existsSync51, statSync as statSync16 } from "node:fs";
65176
+ import { existsSync as existsSync52, statSync as statSync16 } from "node:fs";
64585
65177
  import { cwd as cwd2 } from "node:process";
64586
65178
  async function indexRepoCommand(opts, _config) {
64587
65179
  const repoRoot = resolve33(opts.repoPath ?? cwd2());
64588
65180
  printHeader("Index Repository");
64589
65181
  printInfo(`Indexing: ${repoRoot}`);
64590
- if (!existsSync51(repoRoot)) {
65182
+ if (!existsSync52(repoRoot)) {
64591
65183
  printError(`Path does not exist: ${repoRoot}`);
64592
65184
  process.exit(1);
64593
65185
  }
@@ -64839,7 +65431,7 @@ var config_exports = {};
64839
65431
  __export(config_exports, {
64840
65432
  configCommand: () => configCommand
64841
65433
  });
64842
- import { join as join69, resolve as resolve34 } from "node:path";
65434
+ import { join as join70, resolve as resolve34 } from "node:path";
64843
65435
  import { homedir as homedir17 } from "node:os";
64844
65436
  import { cwd as cwd3 } from "node:process";
64845
65437
  function redactIfSensitive(key, value) {
@@ -64922,7 +65514,7 @@ function handleShow(opts, config) {
64922
65514
  }
64923
65515
  }
64924
65516
  printSection("Config File");
64925
- printInfo(`~/.open-agents/config.json (${join69(homedir17(), ".open-agents", "config.json")})`);
65517
+ printInfo(`~/.open-agents/config.json (${join70(homedir17(), ".open-agents", "config.json")})`);
64926
65518
  printSection("Priority Chain");
64927
65519
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
64928
65520
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -64961,7 +65553,7 @@ function handleSet(opts, _config) {
64961
65553
  const coerced = coerceForSettings(key, value);
64962
65554
  saveProjectSettings(repoRoot, { [key]: coerced });
64963
65555
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
64964
- printInfo(`Saved to ${join69(repoRoot, ".oa", "settings.json")}`);
65556
+ printInfo(`Saved to ${join70(repoRoot, ".oa", "settings.json")}`);
64965
65557
  printInfo("This override applies only when running in this workspace.");
64966
65558
  } catch (err) {
64967
65559
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -65219,8 +65811,8 @@ __export(eval_exports, {
65219
65811
  evalCommand: () => evalCommand
65220
65812
  });
65221
65813
  import { tmpdir as tmpdir10 } from "node:os";
65222
- import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync24 } from "node:fs";
65223
- import { join as join70 } from "node:path";
65814
+ import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync25 } from "node:fs";
65815
+ import { join as join71 } from "node:path";
65224
65816
  async function evalCommand(opts, config) {
65225
65817
  const suiteName = opts.suite ?? "basic";
65226
65818
  const suite = SUITES[suiteName];
@@ -65345,9 +65937,9 @@ async function evalCommand(opts, config) {
65345
65937
  process.exit(failed > 0 ? 1 : 0);
65346
65938
  }
65347
65939
  function createTempEvalRepo() {
65348
- const dir = join70(tmpdir10(), `open-agents-eval-${Date.now()}`);
65349
- mkdirSync25(dir, { recursive: true });
65350
- writeFileSync24(join70(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
65940
+ const dir = join71(tmpdir10(), `open-agents-eval-${Date.now()}`);
65941
+ mkdirSync26(dir, { recursive: true });
65942
+ writeFileSync25(join71(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
65351
65943
  return dir;
65352
65944
  }
65353
65945
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -65407,7 +65999,7 @@ init_updater();
65407
65999
  import { parseArgs as nodeParseArgs2 } from "node:util";
65408
66000
  import { createRequire as createRequire3 } from "node:module";
65409
66001
  import { fileURLToPath as fileURLToPath13 } from "node:url";
65410
- import { dirname as dirname21, join as join71 } from "node:path";
66002
+ import { dirname as dirname21, join as join72 } from "node:path";
65411
66003
 
65412
66004
  // packages/cli/dist/cli.js
65413
66005
  import { createInterface } from "node:readline";
@@ -65514,7 +66106,7 @@ init_output();
65514
66106
  function getVersion4() {
65515
66107
  try {
65516
66108
  const require2 = createRequire3(import.meta.url);
65517
- const pkgPath = join71(dirname21(fileURLToPath13(import.meta.url)), "..", "package.json");
66109
+ const pkgPath = join72(dirname21(fileURLToPath13(import.meta.url)), "..", "package.json");
65518
66110
  const pkg = require2(pkgPath);
65519
66111
  return pkg.version;
65520
66112
  } catch {