open-agents-ai 0.185.22 → 0.185.24

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 +1163 -768
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13741,9 +13741,9 @@ print("${sentinel}")
13741
13741
  if (!this.proc || this.proc.killed) {
13742
13742
  return { success: false, path: "" };
13743
13743
  }
13744
- const { mkdirSync: mkdirSync30, writeFileSync: writeFileSync29 } = await import("node:fs");
13744
+ const { mkdirSync: mkdirSync31, writeFileSync: writeFileSync30 } = await import("node:fs");
13745
13745
  const sessionDir = join22(this.cwd, ".oa", "rlm");
13746
- mkdirSync30(sessionDir, { recursive: true });
13746
+ mkdirSync31(sessionDir, { recursive: true });
13747
13747
  const sessionPath = join22(sessionDir, "session.json");
13748
13748
  try {
13749
13749
  const inspectCode = `
@@ -13767,7 +13767,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13767
13767
  trajectoryCount: this.trajectory.length,
13768
13768
  subCallCount: this.subCallCount
13769
13769
  };
13770
- writeFileSync29(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13770
+ writeFileSync30(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13771
13771
  return { success: true, path: sessionPath };
13772
13772
  }
13773
13773
  } catch {
@@ -13779,11 +13779,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13779
13779
  * what was previously computed. */
13780
13780
  async loadSessionInfo() {
13781
13781
  try {
13782
- const { readFileSync: readFileSync44, existsSync: existsSync56 } = await import("node:fs");
13782
+ const { readFileSync: readFileSync45, existsSync: existsSync57 } = await import("node:fs");
13783
13783
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13784
- if (!existsSync56(sessionPath))
13784
+ if (!existsSync57(sessionPath))
13785
13785
  return null;
13786
- return JSON.parse(readFileSync44(sessionPath, "utf8"));
13786
+ return JSON.parse(readFileSync45(sessionPath, "utf8"));
13787
13787
  } catch {
13788
13788
  return null;
13789
13789
  }
@@ -13960,10 +13960,10 @@ var init_memory_metabolism = __esm({
13960
13960
  const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
13961
13961
  let lessons = [];
13962
13962
  try {
13963
- const { readdirSync: readdirSync23, readFileSync: readFileSync44 } = await import("node:fs");
13963
+ const { readdirSync: readdirSync23, readFileSync: readFileSync45 } = await import("node:fs");
13964
13964
  const files = readdirSync23(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
13965
13965
  for (const file of files) {
13966
- const lines = readFileSync44(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13966
+ const lines = readFileSync45(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13967
13967
  for (const line of lines) {
13968
13968
  try {
13969
13969
  const entry = JSON.parse(line);
@@ -14347,14 +14347,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14347
14347
  * Optionally filter by task type for phase-aware context (FSM paper insight).
14348
14348
  */
14349
14349
  getTopMemoriesSync(k = 5, taskType) {
14350
- const { readFileSync: readFileSync44, existsSync: existsSync56 } = __require("node:fs");
14350
+ const { readFileSync: readFileSync45, existsSync: existsSync57 } = __require("node:fs");
14351
14351
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14352
14352
  const storeFile = join23(metaDir, "store.json");
14353
- if (!existsSync56(storeFile))
14353
+ if (!existsSync57(storeFile))
14354
14354
  return "";
14355
14355
  let store = [];
14356
14356
  try {
14357
- store = JSON.parse(readFileSync44(storeFile, "utf8"));
14357
+ store = JSON.parse(readFileSync45(storeFile, "utf8"));
14358
14358
  } catch {
14359
14359
  return "";
14360
14360
  }
@@ -14376,14 +14376,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14376
14376
  /** Update memory scores based on task outcome. Called after task completion.
14377
14377
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
14378
14378
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
14379
- const { readFileSync: readFileSync44, writeFileSync: writeFileSync29, existsSync: existsSync56, mkdirSync: mkdirSync30 } = __require("node:fs");
14379
+ const { readFileSync: readFileSync45, writeFileSync: writeFileSync30, existsSync: existsSync57, mkdirSync: mkdirSync31 } = __require("node:fs");
14380
14380
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14381
14381
  const storeFile = join23(metaDir, "store.json");
14382
- if (!existsSync56(storeFile))
14382
+ if (!existsSync57(storeFile))
14383
14383
  return;
14384
14384
  let store = [];
14385
14385
  try {
14386
- store = JSON.parse(readFileSync44(storeFile, "utf8"));
14386
+ store = JSON.parse(readFileSync45(storeFile, "utf8"));
14387
14387
  } catch {
14388
14388
  return;
14389
14389
  }
@@ -14407,8 +14407,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14407
14407
  updated = true;
14408
14408
  }
14409
14409
  if (updated) {
14410
- mkdirSync30(metaDir, { recursive: true });
14411
- writeFileSync29(storeFile, JSON.stringify(store, null, 2));
14410
+ mkdirSync31(metaDir, { recursive: true });
14411
+ writeFileSync30(storeFile, JSON.stringify(store, null, 2));
14412
14412
  }
14413
14413
  }
14414
14414
  // ── Storage ──────────────────────────────────────────────────────────
@@ -14830,13 +14830,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14830
14830
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
14831
14831
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
14832
14832
  getRelevantStrategiesSync(k = 3, taskType) {
14833
- const { readFileSync: readFileSync44, existsSync: existsSync56 } = __require("node:fs");
14833
+ const { readFileSync: readFileSync45, existsSync: existsSync57 } = __require("node:fs");
14834
14834
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14835
- if (!existsSync56(archiveFile))
14835
+ if (!existsSync57(archiveFile))
14836
14836
  return "";
14837
14837
  let variants = [];
14838
14838
  try {
14839
- variants = JSON.parse(readFileSync44(archiveFile, "utf8"));
14839
+ variants = JSON.parse(readFileSync45(archiveFile, "utf8"));
14840
14840
  } catch {
14841
14841
  return "";
14842
14842
  }
@@ -14854,13 +14854,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14854
14854
  }
14855
14855
  /** Archive a strategy variant synchronously (for task completion path) */
14856
14856
  archiveVariantSync(strategy, outcome, tags = []) {
14857
- const { readFileSync: readFileSync44, writeFileSync: writeFileSync29, existsSync: existsSync56, mkdirSync: mkdirSync30 } = __require("node:fs");
14857
+ const { readFileSync: readFileSync45, writeFileSync: writeFileSync30, existsSync: existsSync57, mkdirSync: mkdirSync31 } = __require("node:fs");
14858
14858
  const dir = join25(this.cwd, ".oa", "arche");
14859
14859
  const archiveFile = join25(dir, "variants.json");
14860
14860
  let variants = [];
14861
14861
  try {
14862
- if (existsSync56(archiveFile))
14863
- variants = JSON.parse(readFileSync44(archiveFile, "utf8"));
14862
+ if (existsSync57(archiveFile))
14863
+ variants = JSON.parse(readFileSync45(archiveFile, "utf8"));
14864
14864
  } catch {
14865
14865
  }
14866
14866
  variants.push({
@@ -14875,8 +14875,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14875
14875
  });
14876
14876
  if (variants.length > 50)
14877
14877
  variants = variants.slice(-50);
14878
- mkdirSync30(dir, { recursive: true });
14879
- writeFileSync29(archiveFile, JSON.stringify(variants, null, 2));
14878
+ mkdirSync31(dir, { recursive: true });
14879
+ writeFileSync30(archiveFile, JSON.stringify(variants, null, 2));
14880
14880
  }
14881
14881
  async saveArchive(variants) {
14882
14882
  const dir = join25(this.cwd, ".oa", "arche");
@@ -15840,9 +15840,9 @@ var init_vision = __esm({
15840
15840
  if (ollamaResult)
15841
15841
  return ollamaResult;
15842
15842
  try {
15843
- const { execSync: execSync34 } = await import("node:child_process");
15843
+ const { execSync: execSync35 } = await import("node:child_process");
15844
15844
  try {
15845
- execSync34("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
15845
+ execSync35("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
15846
15846
  timeout: 12e4,
15847
15847
  stdio: "pipe"
15848
15848
  });
@@ -15855,7 +15855,7 @@ var init_vision = __esm({
15855
15855
  } catch {
15856
15856
  }
15857
15857
  try {
15858
- execSync34("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15858
+ execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15859
15859
  const retryOllama = await this.tryOllamaVision(buffer, filename, action, prompt, length, start);
15860
15860
  if (retryOllama)
15861
15861
  return retryOllama;
@@ -15963,8 +15963,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
15963
15963
  const errText = await res.text().catch(() => "");
15964
15964
  if (res.status === 404 || /not found|does not exist/i.test(errText)) {
15965
15965
  try {
15966
- const { execSync: execSync34 } = await import("node:child_process");
15967
- execSync34("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15966
+ const { execSync: execSync35 } = await import("node:child_process");
15967
+ execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15968
15968
  res = await fetch(`${ollamaHost}/api/generate`, {
15969
15969
  method: "POST",
15970
15970
  headers: { "Content-Type": "application/json" },
@@ -27351,10 +27351,10 @@ ${marker}` : marker);
27351
27351
  if (!this._workingDirectory)
27352
27352
  return;
27353
27353
  try {
27354
- const { mkdirSync: mkdirSync30, writeFileSync: writeFileSync29 } = __require("node:fs");
27355
- const { join: join76 } = __require("node:path");
27356
- const sessionDir = join76(this._workingDirectory, ".oa", "session", this._sessionId);
27357
- mkdirSync30(sessionDir, { recursive: true });
27354
+ const { mkdirSync: mkdirSync31, writeFileSync: writeFileSync30 } = __require("node:fs");
27355
+ const { join: join77 } = __require("node:path");
27356
+ const sessionDir = join77(this._workingDirectory, ".oa", "session", this._sessionId);
27357
+ mkdirSync31(sessionDir, { recursive: true });
27358
27358
  const checkpoint = {
27359
27359
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
27360
27360
  sessionId: this._sessionId,
@@ -27366,7 +27366,7 @@ ${marker}` : marker);
27366
27366
  memexEntryCount: this._memexArchive.size,
27367
27367
  fileRegistrySize: this._fileRegistry.size
27368
27368
  };
27369
- writeFileSync29(join76(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27369
+ writeFileSync30(join77(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27370
27370
  } catch {
27371
27371
  }
27372
27372
  }
@@ -35253,97 +35253,98 @@ function generateFrontendHTML() {
35253
35253
  <head>
35254
35254
  <meta charset="UTF-8">
35255
35255
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
35256
- <title>Open Agents \u2014 Live Voice Session</title>
35256
+ <title>OA \u2014 Voice</title>
35257
35257
  <style>
35258
35258
  * { margin: 0; padding: 0; box-sizing: border-box; }
35259
35259
  body {
35260
- background: #0a0a0f;
35261
- color: #c4b5fd;
35262
- font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', 'JetBrains Mono', monospace;
35260
+ background: #1a1a1e;
35261
+ color: #b0b0b0;
35262
+ font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
35263
35263
  display: flex;
35264
35264
  flex-direction: column;
35265
- align-items: center;
35266
- justify-content: center;
35267
35265
  min-height: 100vh;
35268
- overflow: hidden;
35269
35266
  }
35267
+ #header {
35268
+ background: #1e1e22;
35269
+ padding: 8px 16px;
35270
+ display: flex;
35271
+ align-items: center;
35272
+ gap: 12px;
35273
+ border-bottom: 1px solid #2a2a30;
35274
+ }
35275
+ #header .accent { color: #b2920a; font-weight: bold; font-size: 0.8rem; }
35276
+ #header .status { font-size: 0.7rem; color: #555; }
35277
+ #header .status.live { color: #b2920a; }
35270
35278
  #waveform {
35271
- width: 90%; max-width: 700px;
35272
- height: 80px;
35279
+ height: 48px;
35273
35280
  display: flex;
35274
35281
  align-items: center;
35275
35282
  justify-content: center;
35276
- font-size: 2rem;
35283
+ font-size: 1.6rem;
35277
35284
  line-height: 1;
35278
- letter-spacing: 0.05em;
35285
+ letter-spacing: 0.04em;
35279
35286
  white-space: nowrap;
35280
35287
  overflow: hidden;
35281
- margin-bottom: 1.5rem;
35282
35288
  user-select: none;
35289
+ background: #1e1e22;
35290
+ border-bottom: 1px solid #2a2a30;
35291
+ }
35292
+ #conversation {
35293
+ flex: 1;
35294
+ overflow-y: auto;
35295
+ padding: 12px 16px;
35296
+ }
35297
+ .msg {
35298
+ padding: 6px 0;
35299
+ font-size: 0.82rem;
35300
+ line-height: 1.4;
35301
+ }
35302
+ .msg.user { color: #888; }
35303
+ .msg.user::before { content: '\u25B8 '; color: #555; }
35304
+ .msg.agent { color: #b2920a; }
35305
+ .msg.agent::before { content: '\u25B9 '; color: #b2920a; }
35306
+ #footer {
35307
+ background: #1e1e22;
35308
+ padding: 8px 16px;
35309
+ display: flex;
35310
+ align-items: center;
35311
+ gap: 10px;
35312
+ border-top: 1px solid #2a2a30;
35283
35313
  }
35284
- #title {
35285
- font-size: 0.75rem;
35286
- color: #7c3aed;
35287
- letter-spacing: 0.3em;
35288
- text-transform: uppercase;
35289
- margin-bottom: 1.5rem;
35290
- }
35291
- #status {
35292
- font-size: 0.85rem;
35293
- color: #6b6b8a;
35294
- margin-bottom: 1rem;
35295
- }
35296
- #status .connected { color: #a78bfa; }
35297
- #status .disconnected { color: #f87171; }
35298
- #transcripts {
35299
- width: 90%; max-width: 600px; max-height: 40vh;
35300
- overflow-y: auto; padding: 1rem;
35301
- background: rgba(139,92,246,0.04);
35302
- border-radius: 4px;
35303
- border: 1px solid rgba(139,92,246,0.12);
35304
- }
35305
- .transcript {
35306
- padding: 0.35rem 0;
35307
- border-bottom: 1px solid rgba(139,92,246,0.08);
35308
- font-size: 0.8rem;
35309
- color: #a5a0c8;
35310
- }
35311
- .transcript .speaker { font-weight: bold; margin-right: 0.5rem; }
35312
- .transcript .speaker.user { color: #c084fc; }
35313
- .transcript .speaker.agent { color: #8b5cf6; }
35314
- #controls { margin-top: 1.5rem; }
35315
35314
  button {
35316
- background: rgba(139,92,246,0.12);
35317
- border: 1px solid rgba(139,92,246,0.3);
35318
- color: #c4b5fd;
35319
- padding: 0.5rem 1.4rem;
35320
- border-radius: 4px;
35315
+ background: #2a2a30;
35316
+ border: 1px solid #3a3a42;
35317
+ color: #b2920a;
35318
+ padding: 6px 16px;
35319
+ border-radius: 3px;
35321
35320
  font-family: inherit;
35322
- font-size: 0.8rem;
35321
+ font-size: 0.75rem;
35323
35322
  cursor: pointer;
35324
- transition: all 0.2s;
35325
- letter-spacing: 0.05em;
35323
+ transition: background 0.15s;
35326
35324
  }
35327
- button:hover { background: rgba(139,92,246,0.22); }
35328
- button.active { background: rgba(239,68,68,0.15); border-color: rgba(239,68,68,0.35); color: #fca5a5; }
35325
+ button:hover { background: #3a3a42; }
35326
+ button.active { background: #3a2a10; border-color: #b2920a; }
35327
+ #footer .hint { font-size: 0.65rem; color: #444; }
35329
35328
  </style>
35330
35329
  </head>
35331
35330
  <body>
35332
- <div id="title">open agents &mdash; voice session</div>
35333
- <div id="waveform"></div>
35334
- <div id="status">
35335
- <span class="disconnected">connecting...</span>
35331
+ <div id="header">
35332
+ <span class="accent">OA</span>
35333
+ <span id="status" class="status">connecting</span>
35336
35334
  </div>
35337
- <div id="transcripts"></div>
35338
- <div id="controls">
35339
- <button id="micBtn" onclick="toggleMic()">start mic</button>
35335
+ <div id="waveform"></div>
35336
+ <div id="conversation"></div>
35337
+ <div id="footer">
35338
+ <button id="micBtn" onclick="toggleMic()">mic</button>
35339
+ <span class="hint" id="hint">tap to start</span>
35340
35340
  </div>
35341
35341
 
35342
35342
  <script>
35343
35343
  const waveEl = document.getElementById('waveform');
35344
35344
  const statusEl = document.getElementById('status');
35345
- const transcriptsEl = document.getElementById('transcripts');
35345
+ const convoEl = document.getElementById('conversation');
35346
35346
  const micBtn = document.getElementById('micBtn');
35347
+ const hintEl = document.getElementById('hint');
35347
35348
 
35348
35349
  // ---------------------------------------------------------------------------
35349
35350
  // Braille waveform \u2014 ported from TUI braille-spinner.ts
@@ -35354,10 +35355,10 @@ const DENSITY = [
35354
35355
  ];
35355
35356
  const WAVE = [...DENSITY, ...DENSITY.slice(1, -1).reverse()]; // 16 entries
35356
35357
 
35357
- // Color themes: arrays of 9 CSS colors (sparse -> dense)
35358
- const THEME_IDLE = ['#1e1b2e','#3b2d6b','#5b3fa0','#7c3aed','#8b5cf6','#a78bfa','#c4b5fd','#ddd6fe','#ede9fe'];
35359
- const THEME_SPEAKING = ['#0a2e1a','#0d5f2f','#15803d','#22c55e','#4ade80','#86efac','#bbf7d0','#dcfce7','#f0fdf4'];
35360
- const THEME_LISTENING = ['#2e1b0a','#6b3d0d','#a05f15','#ed8b3a','#f6a05c','#fabe8b','#fdd5b5','#fde6d6','#fef3e9'];
35358
+ // Color themes: TUI-aligned dark grey + yellow accent
35359
+ const THEME_IDLE = ['#1e1e22','#2a2a30','#333338','#3e3e44','#4a4a52','#555560','#666670','#777780','#888890'];
35360
+ const THEME_SPEAKING = ['#1e1e22','#2a2510','#3a3518','#4a4520','#5a5528','#6a6530','#8a7a20','#a89010','#b2920a'];
35361
+ const THEME_LISTENING = ['#1e1e22','#2a2818','#3a3820','#4a4828','#5a5830','#6a6838','#8a8830','#a8a020','#b2920a'];
35361
35362
 
35362
35363
  function buildColorRamp(ramp) {
35363
35364
  return [...ramp, ...ramp.slice(1, -1).reverse()]; // 16 entries
@@ -35459,7 +35460,8 @@ function connect() {
35459
35460
  ws.onopen = () => {
35460
35461
  connecting = false;
35461
35462
  if (disconnectGrace) { clearTimeout(disconnectGrace); disconnectGrace = null; }
35462
- statusEl.innerHTML = '<span class="connected">connected</span>';
35463
+ statusEl.textContent = 'connected';
35464
+ statusEl.className = 'status live';
35463
35465
  reconnectDelay = 1000;
35464
35466
  };
35465
35467
 
@@ -35471,7 +35473,8 @@ function connect() {
35471
35473
  if (!disconnectGrace) {
35472
35474
  disconnectGrace = setTimeout(() => {
35473
35475
  disconnectGrace = null;
35474
- statusEl.innerHTML = '<span class="disconnected">reconnecting...</span>';
35476
+ statusEl.textContent = 'reconnecting';
35477
+ statusEl.className = 'status';
35475
35478
  }, 2000);
35476
35479
  }
35477
35480
  reconnectTimer = setTimeout(connect, reconnectDelay);
@@ -35503,11 +35506,10 @@ function connect() {
35503
35506
 
35504
35507
  function addTranscript(speaker, text) {
35505
35508
  const div = document.createElement('div');
35506
- div.className = 'transcript';
35507
- div.innerHTML = '<span class="speaker ' + speaker + '">' +
35508
- (speaker === 'user' ? 'you' : 'agent') + ':</span> ' + escapeHtml(text);
35509
- transcriptsEl.appendChild(div);
35510
- transcriptsEl.scrollTop = transcriptsEl.scrollHeight;
35509
+ div.className = 'msg ' + speaker;
35510
+ div.textContent = text;
35511
+ convoEl.appendChild(div);
35512
+ convoEl.scrollTop = convoEl.scrollHeight;
35511
35513
  }
35512
35514
 
35513
35515
  function escapeHtml(s) {
@@ -35565,11 +35567,12 @@ async function toggleMic() {
35565
35567
  scriptProcessor.connect(micCtx.destination);
35566
35568
  micActive = true;
35567
35569
  waveState = 'listening';
35568
- micBtn.textContent = 'stop mic';
35570
+ micBtn.textContent = 'stop';
35569
35571
  micBtn.classList.add('active');
35572
+ hintEl.textContent = 'listening...';
35570
35573
  ws.send(JSON.stringify({ type: 'mic_start', username: 'web-user' }));
35571
35574
  } catch (err) {
35572
- statusEl.innerHTML = '<span class="disconnected">mic error: ' + err.message + '</span>';
35575
+ hintEl.textContent = 'mic error: ' + err.message;
35573
35576
  }
35574
35577
  }
35575
35578
 
@@ -35579,8 +35582,9 @@ function stopMic() {
35579
35582
  waveState = 'idle';
35580
35583
  if (scriptProcessor) { scriptProcessor.disconnect(); scriptProcessor = null; }
35581
35584
  if (micStream) { micStream.getTracks().forEach(t => t.stop()); micStream = null; }
35582
- micBtn.textContent = 'start mic';
35585
+ micBtn.textContent = 'mic';
35583
35586
  micBtn.classList.remove('active');
35587
+ hintEl.textContent = 'tap to start';
35584
35588
  if (ws && ws.readyState === 1) {
35585
35589
  ws.send(JSON.stringify({ type: 'mic_stop' }));
35586
35590
  }
@@ -38525,6 +38529,7 @@ var init_call_agent = __esm({
38525
38529
  tier;
38526
38530
  clientId;
38527
38531
  runner = null;
38532
+ backend = null;
38528
38533
  config;
38529
38534
  repoRoot;
38530
38535
  opts;
@@ -38543,6 +38548,7 @@ var init_call_agent = __esm({
38543
38548
  /** Initialize the runner with appropriate tools for the access tier */
38544
38549
  async init() {
38545
38550
  const backend = new OllamaAgenticBackend(this.config.backendUrl, this.config.model, this.config.apiKey);
38551
+ this.backend = backend;
38546
38552
  const feed = getActivityFeed();
38547
38553
  const systemPrompt = this.buildSystemPrompt();
38548
38554
  const runnerOpts = {
@@ -38652,21 +38658,46 @@ var init_call_agent = __esm({
38652
38658
  const historyContext = this.conversationHistory.slice(-10).map((h) => `${h.role === "user" ? "User" : "You"}: ${h.text}`).join("\n");
38653
38659
  const feed = getActivityFeed();
38654
38660
  const activitySummary = feed.getSummary(this.tier === "admin" ? 20 : 10, this.tier === "admin");
38655
- const wantsAction = /\b(read|open|show|run|execute|check|look at|find|search|grep|edit|write|fix|test|build|deploy|install)\b/i.test(text) && !/\b(how are you|what's up|hello|hi|hey|can you hear|stop|quit|bye)\b/i.test(text);
38656
- const taskPrompt = [
38657
- `User said: "${text}"`,
38658
- "",
38659
- historyContext ? `Conversation so far:
38661
+ const wantsAction = /\b(read|open|show|run|execute|check|look at|find|search|grep|edit|write|fix|test|build|deploy|install|create|delete|remove|update|change|modify|commit|push|pull)\b/i.test(text) && !/\b(how are you|what's up|hello|hi|hey|can you hear|stop|quit|bye|thanks|thank you|ok|okay|sure|yeah|yes|no)\b/i.test(text);
38662
+ if (!wantsAction) {
38663
+ try {
38664
+ const chatMessages = [
38665
+ { role: "system", content: this.buildSystemPrompt() },
38666
+ ...this.conversationHistory.slice(-6).map((h) => ({
38667
+ role: h.role === "user" ? "user" : "assistant",
38668
+ content: h.text
38669
+ })),
38670
+ { role: "user", content: text }
38671
+ ];
38672
+ const chatResult = await this.backend.chatCompletion({
38673
+ messages: chatMessages,
38674
+ tools: [],
38675
+ temperature: 0.4,
38676
+ maxTokens: 256,
38677
+ timeoutMs: 15e3
38678
+ });
38679
+ const reply = chatResult.choices[0]?.message?.content ?? "I heard you.";
38680
+ this.conversationHistory.push({ role: "assistant", text: reply });
38681
+ this.emit("response", reply);
38682
+ } catch {
38683
+ this.emit("response", "Sorry, I couldn't process that.");
38684
+ }
38685
+ } else {
38686
+ const taskPrompt = [
38687
+ `User said: "${text}"`,
38688
+ "",
38689
+ historyContext ? `Conversation so far:
38660
38690
  ${historyContext}
38661
38691
  ` : "",
38662
- `Background activity:
38692
+ `Background activity:
38663
38693
  ${activitySummary}
38664
38694
  `,
38665
- wantsAction ? "The user is requesting an action. You may use tools, then call task_complete with a brief spoken summary of what you did." : "RESPOND IMMEDIATELY \u2014 call task_complete with your spoken reply. Do NOT use any tools. Just answer conversationally in 1-3 sentences."
38666
- ].join("\n");
38667
- const result = await this.runner.run(taskPrompt, `Working directory: ${this.repoRoot}`);
38668
- if (result.summary) {
38669
- this.conversationHistory.push({ role: "assistant", text: result.summary });
38695
+ "The user is requesting an action. Use tools as needed, then call task_complete with a brief spoken summary of what you did (1-2 sentences)."
38696
+ ].join("\n");
38697
+ const result = await this.runner.run(taskPrompt, `Working directory: ${this.repoRoot}`);
38698
+ if (result.summary) {
38699
+ this.conversationHistory.push({ role: "assistant", text: result.summary });
38700
+ }
38670
38701
  }
38671
38702
  } catch (err) {
38672
38703
  this.emit("error", err instanceof Error ? err : new Error(String(err)));
@@ -38875,26 +38906,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
38875
38906
  async function fetchPeerModels(peerId, authKey) {
38876
38907
  try {
38877
38908
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
38878
- const { existsSync: existsSync56, readFileSync: readFileSync44 } = await import("node:fs");
38879
- const { join: join76 } = await import("node:path");
38909
+ const { existsSync: existsSync57, readFileSync: readFileSync45 } = await import("node:fs");
38910
+ const { join: join77 } = await import("node:path");
38880
38911
  const cwd4 = process.cwd();
38881
38912
  const nexusTool = new NexusTool2(cwd4);
38882
38913
  const nexusDir = nexusTool.getNexusDir();
38883
38914
  let isLocalPeer = false;
38884
38915
  try {
38885
- const statusPath = join76(nexusDir, "status.json");
38886
- if (existsSync56(statusPath)) {
38887
- const status = JSON.parse(readFileSync44(statusPath, "utf8"));
38916
+ const statusPath = join77(nexusDir, "status.json");
38917
+ if (existsSync57(statusPath)) {
38918
+ const status = JSON.parse(readFileSync45(statusPath, "utf8"));
38888
38919
  if (status.peerId === peerId)
38889
38920
  isLocalPeer = true;
38890
38921
  }
38891
38922
  } catch {
38892
38923
  }
38893
38924
  if (isLocalPeer) {
38894
- const pricingPath = join76(nexusDir, "pricing.json");
38895
- if (existsSync56(pricingPath)) {
38925
+ const pricingPath = join77(nexusDir, "pricing.json");
38926
+ if (existsSync57(pricingPath)) {
38896
38927
  try {
38897
- const pricing = JSON.parse(readFileSync44(pricingPath, "utf8"));
38928
+ const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
38898
38929
  const localModels = (pricing.models || []).map((m) => ({
38899
38930
  name: m.model || "unknown",
38900
38931
  size: m.parameterSize || "",
@@ -38908,10 +38939,10 @@ async function fetchPeerModels(peerId, authKey) {
38908
38939
  }
38909
38940
  }
38910
38941
  }
38911
- const cachePath = join76(nexusDir, "peer-models-cache.json");
38912
- if (existsSync56(cachePath)) {
38942
+ const cachePath = join77(nexusDir, "peer-models-cache.json");
38943
+ if (existsSync57(cachePath)) {
38913
38944
  try {
38914
- const cache4 = JSON.parse(readFileSync44(cachePath, "utf8"));
38945
+ const cache4 = JSON.parse(readFileSync45(cachePath, "utf8"));
38915
38946
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
38916
38947
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
38917
38948
  if (age < 5 * 60 * 1e3) {
@@ -39026,10 +39057,10 @@ async function fetchPeerModels(peerId, authKey) {
39026
39057
  } catch {
39027
39058
  }
39028
39059
  if (isLocalPeer) {
39029
- const pricingPath = join76(nexusDir, "pricing.json");
39030
- if (existsSync56(pricingPath)) {
39060
+ const pricingPath = join77(nexusDir, "pricing.json");
39061
+ if (existsSync57(pricingPath)) {
39031
39062
  try {
39032
- const pricing = JSON.parse(readFileSync44(pricingPath, "utf8"));
39063
+ const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
39033
39064
  return (pricing.models || []).map((m) => ({
39034
39065
  name: m.model || "unknown",
39035
39066
  size: m.parameterSize || "",
@@ -40693,13 +40724,321 @@ var init_tui_select = __esm({
40693
40724
  }
40694
40725
  });
40695
40726
 
40727
+ // packages/cli/dist/tui/personaplex.js
40728
+ var personaplex_exports = {};
40729
+ __export(personaplex_exports, {
40730
+ detectPersonaPlexCapability: () => detectPersonaPlexCapability,
40731
+ getPersonaPlexWSUrl: () => getPersonaPlexWSUrl,
40732
+ installPersonaPlex: () => installPersonaPlex,
40733
+ isPersonaPlexInstalled: () => isPersonaPlexInstalled,
40734
+ isPersonaPlexRunning: () => isPersonaPlexRunning,
40735
+ startPersonaPlexDaemon: () => startPersonaPlexDaemon,
40736
+ stopPersonaPlex: () => stopPersonaPlex
40737
+ });
40738
+ import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, mkdirSync as mkdirSync15 } from "node:fs";
40739
+ import { join as join54 } from "node:path";
40740
+ import { homedir as homedir13 } from "node:os";
40741
+ import { execSync as execSync27, spawn as spawn19 } from "node:child_process";
40742
+ function detectPersonaPlexCapability() {
40743
+ try {
40744
+ const nvsmi = execSync27("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
40745
+ encoding: "utf8",
40746
+ timeout: 5e3,
40747
+ stdio: "pipe"
40748
+ }).trim();
40749
+ if (!nvsmi) {
40750
+ return { supported: false, reason: "No NVIDIA GPU detected", gpuName: "", vramGB: 0 };
40751
+ }
40752
+ const [gpuName, vramMB] = nvsmi.split("\n")[0].split(", ");
40753
+ const vramGB = parseInt(vramMB ?? "0", 10) / 1024;
40754
+ if (vramGB < 16) {
40755
+ return { supported: false, reason: `GPU has ${vramGB.toFixed(1)}GB VRAM (need \u226516GB)`, gpuName: gpuName ?? "", vramGB };
40756
+ }
40757
+ try {
40758
+ execSync27('python3 -c "import torch; assert torch.cuda.is_available()"', {
40759
+ timeout: 1e4,
40760
+ stdio: "pipe"
40761
+ });
40762
+ } catch {
40763
+ return { supported: false, reason: "PyTorch CUDA not available", gpuName: gpuName ?? "", vramGB };
40764
+ }
40765
+ return { supported: true, reason: "OK", gpuName: gpuName ?? "", vramGB };
40766
+ } catch {
40767
+ return { supported: false, reason: "nvidia-smi not found", gpuName: "", vramGB: 0 };
40768
+ }
40769
+ }
40770
+ function isPersonaPlexRunning() {
40771
+ if (!existsSync37(PID_FILE))
40772
+ return false;
40773
+ const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
40774
+ if (isNaN(pid) || pid <= 0)
40775
+ return false;
40776
+ try {
40777
+ process.kill(pid, 0);
40778
+ return true;
40779
+ } catch {
40780
+ return false;
40781
+ }
40782
+ }
40783
+ function getPersonaPlexWSUrl() {
40784
+ if (!isPersonaPlexRunning())
40785
+ return null;
40786
+ if (!existsSync37(PORT_FILE))
40787
+ return null;
40788
+ const port = parseInt(readFileSync28(PORT_FILE, "utf8").trim(), 10);
40789
+ return isNaN(port) ? null : `ws://127.0.0.1:${port}`;
40790
+ }
40791
+ function isPersonaPlexInstalled() {
40792
+ return existsSync37(join54(PERSONAPLEX_DIR, "model_ready"));
40793
+ }
40794
+ async function installPersonaPlex(onInfo) {
40795
+ const log = onInfo ?? (() => {
40796
+ });
40797
+ mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
40798
+ const venvDir = join54(PERSONAPLEX_DIR, "venv");
40799
+ if (!existsSync37(venvDir)) {
40800
+ log("Creating Python virtual environment...");
40801
+ try {
40802
+ execSync27(`python3 -m venv "${venvDir}"`, { timeout: 6e4, stdio: "pipe" });
40803
+ } catch (err) {
40804
+ log(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
40805
+ return false;
40806
+ }
40807
+ }
40808
+ const pip = process.platform === "win32" ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
40809
+ const python = process.platform === "win32" ? join54(venvDir, "Scripts", "python.exe") : join54(venvDir, "bin", "python3");
40810
+ log("Installing PersonaPlex dependencies (torch, transformers, websockets)...");
40811
+ try {
40812
+ execSync27(`"${pip}" install --quiet torch torchaudio transformers websockets soundfile huggingface_hub`, { timeout: 3e5, stdio: "pipe" });
40813
+ } catch (err) {
40814
+ log(`Dependency install failed: ${err instanceof Error ? err.message : String(err)}`);
40815
+ return false;
40816
+ }
40817
+ log("Downloading PersonaPlex-7B model (~14GB, this may take a while)...");
40818
+ try {
40819
+ execSync27(`"${python}" -c "from huggingface_hub import snapshot_download; snapshot_download('nvidia/personaplex-7b-v1', local_dir='${join54(PERSONAPLEX_DIR, "model").replace(/\\/g, "\\\\")}')"`, { timeout: 36e5, stdio: "pipe" });
40820
+ } catch (err) {
40821
+ log(`Model download failed: ${err instanceof Error ? err.message : String(err)}`);
40822
+ return false;
40823
+ }
40824
+ writeFileSync16(join54(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
40825
+ log("PersonaPlex installed successfully.");
40826
+ return true;
40827
+ }
40828
+ function writeDaemonScript() {
40829
+ const scriptPath2 = join54(PERSONAPLEX_DIR, "daemon.py");
40830
+ const modelDir2 = join54(PERSONAPLEX_DIR, "model");
40831
+ const script = `#!/usr/bin/env python3
40832
+ """PersonaPlex daemon \u2014 full-duplex voice WebSocket server."""
40833
+ import asyncio
40834
+ import json
40835
+ import os
40836
+ import signal
40837
+ import sys
40838
+ import numpy as np
40839
+
40840
+ # Write PID file
40841
+ pid_file = os.path.join(os.path.dirname(__file__), "daemon.pid")
40842
+ with open(pid_file, "w") as f:
40843
+ f.write(str(os.getpid()))
40844
+
40845
+ try:
40846
+ import torch
40847
+ import torchaudio
40848
+ from transformers import AutoModel, AutoProcessor
40849
+ import websockets
40850
+ import soundfile as sf
40851
+ except ImportError as e:
40852
+ print(f"Missing dependency: {e}", file=sys.stderr)
40853
+ sys.exit(1)
40854
+
40855
+ MODEL_DIR = ${JSON.stringify(modelDir2)}
40856
+ SAMPLE_RATE = 24000
40857
+ PORT = int(os.environ.get("PERSONAPLEX_PORT", "0")) # 0 = auto-assign
40858
+
40859
+ print("Loading PersonaPlex model...", file=sys.stderr)
40860
+ device = "cuda" if torch.cuda.is_available() else "cpu"
40861
+ dtype = torch.bfloat16 if device == "cuda" else torch.float32
40862
+
40863
+ try:
40864
+ model = AutoModel.from_pretrained(MODEL_DIR, trust_remote_code=True, torch_dtype=dtype)
40865
+ model = model.to(device)
40866
+ model.eval()
40867
+ processor = AutoProcessor.from_pretrained(MODEL_DIR, trust_remote_code=True)
40868
+ print(f"Model loaded on {device}", file=sys.stderr)
40869
+ except Exception as e:
40870
+ print(f"Model load failed: {e}", file=sys.stderr)
40871
+ sys.exit(1)
40872
+
40873
+ # Persona state
40874
+ persona_text = "You are a helpful voice assistant."
40875
+ voice_prompt = None # Audio conditioning tensor
40876
+
40877
+ async def handle_client(websocket, path):
40878
+ """Handle a single WebSocket client connection."""
40879
+ global persona_text, voice_prompt
40880
+ print(f"Client connected from {websocket.remote_address}", file=sys.stderr)
40881
+
40882
+ try:
40883
+ async for message in websocket:
40884
+ if isinstance(message, str):
40885
+ # JSON control message
40886
+ try:
40887
+ msg = json.loads(message)
40888
+ if msg.get("type") == "persona":
40889
+ persona_text = msg.get("text", persona_text)
40890
+ print(f"Persona updated: {persona_text[:60]}", file=sys.stderr)
40891
+ elif msg.get("type") == "voice_prompt":
40892
+ # Audio conditioning: base64 PCM \u2192 tensor
40893
+ import base64
40894
+ pcm_bytes = base64.b64decode(msg["audio"])
40895
+ audio = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32) / 32768.0
40896
+ voice_prompt = torch.tensor(audio, dtype=dtype, device=device).unsqueeze(0)
40897
+ print(f"Voice prompt set ({len(audio)} samples)", file=sys.stderr)
40898
+ elif msg.get("type") == "keepalive":
40899
+ await websocket.send(json.dumps({"type": "pong"}))
40900
+ except json.JSONDecodeError:
40901
+ pass
40902
+ else:
40903
+ # Binary audio data: PCM Int16 @ 24kHz
40904
+ pcm = np.frombuffer(message, dtype=np.int16).astype(np.float32) / 32768.0
40905
+ audio_tensor = torch.tensor(pcm, dtype=dtype, device=device).unsqueeze(0)
40906
+
40907
+ # Generate response
40908
+ with torch.no_grad():
40909
+ inputs = processor(
40910
+ audio=audio_tensor,
40911
+ text=persona_text,
40912
+ sampling_rate=SAMPLE_RATE,
40913
+ return_tensors="pt"
40914
+ ).to(device)
40915
+
40916
+ if voice_prompt is not None:
40917
+ inputs["voice_prompt"] = voice_prompt
40918
+
40919
+ outputs = model.generate(**inputs, max_new_tokens=512)
40920
+
40921
+ # Extract audio response
40922
+ if hasattr(outputs, "audio"):
40923
+ response_pcm = outputs.audio.cpu().numpy().flatten()
40924
+ else:
40925
+ response_pcm = outputs[0].cpu().numpy().flatten()
40926
+
40927
+ # Convert to Int16 and send
40928
+ response_int16 = (response_pcm * 32767).astype(np.int16)
40929
+ await websocket.send(response_int16.tobytes())
40930
+
40931
+ # Send text if available
40932
+ if hasattr(outputs, "text") and outputs.text:
40933
+ await websocket.send(json.dumps({
40934
+ "type": "transcript",
40935
+ "speaker": "agent",
40936
+ "text": outputs.text
40937
+ }))
40938
+
40939
+ except websockets.exceptions.ConnectionClosed:
40940
+ print("Client disconnected", file=sys.stderr)
40941
+
40942
+ async def main():
40943
+ port = PORT
40944
+ server = await websockets.serve(handle_client, "127.0.0.1", port)
40945
+ actual_port = server.sockets[0].getsockname()[1]
40946
+
40947
+ # Write port file
40948
+ port_file = os.path.join(os.path.dirname(__file__), "daemon.port")
40949
+ with open(port_file, "w") as f:
40950
+ f.write(str(actual_port))
40951
+
40952
+ print(f"PersonaPlex daemon listening on ws://127.0.0.1:{actual_port}", file=sys.stderr)
40953
+
40954
+ # Handle shutdown
40955
+ loop = asyncio.get_event_loop()
40956
+ stop = asyncio.Future()
40957
+ for sig in (signal.SIGINT, signal.SIGTERM):
40958
+ loop.add_signal_handler(sig, stop.set_result, None)
40959
+ await stop
40960
+ server.close()
40961
+ await server.wait_closed()
40962
+
40963
+ asyncio.run(main())
40964
+ `;
40965
+ writeFileSync16(scriptPath2, script, "utf8");
40966
+ return scriptPath2;
40967
+ }
40968
+ async function startPersonaPlexDaemon(onInfo) {
40969
+ const log = onInfo ?? (() => {
40970
+ });
40971
+ if (isPersonaPlexRunning()) {
40972
+ const url = getPersonaPlexWSUrl();
40973
+ if (url) {
40974
+ log(`PersonaPlex already running at ${url}`);
40975
+ return url;
40976
+ }
40977
+ }
40978
+ if (!isPersonaPlexInstalled()) {
40979
+ log("PersonaPlex not installed. Run /voice personaplex to set up.");
40980
+ return null;
40981
+ }
40982
+ mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
40983
+ const scriptPath2 = writeDaemonScript();
40984
+ const venvPython2 = process.platform === "win32" ? join54(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join54(PERSONAPLEX_DIR, "venv", "bin", "python3");
40985
+ log("Starting PersonaPlex daemon...");
40986
+ const child = spawn19(venvPython2, [scriptPath2], {
40987
+ stdio: ["ignore", "pipe", "pipe"],
40988
+ detached: true,
40989
+ env: { ...process.env, PERSONAPLEX_PORT: "0" }
40990
+ });
40991
+ child.unref();
40992
+ const startTime = Date.now();
40993
+ const timeout = 6e4;
40994
+ while (Date.now() - startTime < timeout) {
40995
+ if (existsSync37(PORT_FILE)) {
40996
+ const port = parseInt(readFileSync28(PORT_FILE, "utf8").trim(), 10);
40997
+ if (!isNaN(port) && port > 0) {
40998
+ const url = `ws://127.0.0.1:${port}`;
40999
+ log(`PersonaPlex ready at ${url}`);
41000
+ return url;
41001
+ }
41002
+ }
41003
+ await new Promise((r) => setTimeout(r, 1e3));
41004
+ }
41005
+ log("PersonaPlex daemon failed to start within 60s.");
41006
+ return null;
41007
+ }
41008
+ function stopPersonaPlex() {
41009
+ if (!existsSync37(PID_FILE))
41010
+ return;
41011
+ const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
41012
+ if (isNaN(pid) || pid <= 0)
41013
+ return;
41014
+ try {
41015
+ if (process.platform === "win32") {
41016
+ execSync27(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
41017
+ } else {
41018
+ process.kill(pid, "SIGTERM");
41019
+ }
41020
+ } catch {
41021
+ }
41022
+ }
41023
+ var PERSONAPLEX_DIR, PID_FILE, PORT_FILE, LOG_FILE;
41024
+ var init_personaplex = __esm({
41025
+ "packages/cli/dist/tui/personaplex.js"() {
41026
+ "use strict";
41027
+ init_render();
41028
+ PERSONAPLEX_DIR = join54(homedir13(), ".open-agents", "voice", "personaplex");
41029
+ PID_FILE = join54(PERSONAPLEX_DIR, "daemon.pid");
41030
+ PORT_FILE = join54(PERSONAPLEX_DIR, "daemon.port");
41031
+ LOG_FILE = join54(PERSONAPLEX_DIR, "daemon.log");
41032
+ }
41033
+ });
41034
+
40696
41035
  // packages/cli/dist/tui/setup.js
40697
41036
  import * as readline from "node:readline";
40698
- import { execSync as execSync27, spawn as spawn19, exec as exec2 } from "node:child_process";
41037
+ import { execSync as execSync28, spawn as spawn20, exec as exec2 } from "node:child_process";
40699
41038
  import { promisify as promisify6 } from "node:util";
40700
- import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
40701
- import { join as join54 } from "node:path";
40702
- import { homedir as homedir13, platform as platform2 } from "node:os";
41039
+ import { existsSync as existsSync38, writeFileSync as writeFileSync17, readFileSync as readFileSync29, appendFileSync as appendFileSync2, mkdirSync as mkdirSync16 } from "node:fs";
41040
+ import { join as join55 } from "node:path";
41041
+ import { homedir as homedir14, platform as platform2 } from "node:os";
40703
41042
  async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
40704
41043
  if (_toolSupportCache.has(modelName))
40705
41044
  return _toolSupportCache.get(modelName);
@@ -40730,7 +41069,7 @@ function detectSystemSpecs() {
40730
41069
  let gpuVramGB = 0;
40731
41070
  let gpuName = "";
40732
41071
  try {
40733
- const memInfo = execSync27("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
41072
+ const memInfo = execSync28("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
40734
41073
  encoding: "utf8",
40735
41074
  timeout: 5e3
40736
41075
  });
@@ -40750,7 +41089,7 @@ function detectSystemSpecs() {
40750
41089
  } catch {
40751
41090
  }
40752
41091
  try {
40753
- const nvidiaSmi = execSync27("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
41092
+ const nvidiaSmi = execSync28("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
40754
41093
  const lines = nvidiaSmi.trim().split("\n");
40755
41094
  if (lines.length > 0) {
40756
41095
  for (const line of lines) {
@@ -40921,7 +41260,7 @@ function ensureCurl() {
40921
41260
  for (const s of strategies) {
40922
41261
  if (hasCmd(s.check)) {
40923
41262
  try {
40924
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
41263
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
40925
41264
  if (hasCmd("curl")) {
40926
41265
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
40927
41266
  `);
@@ -40935,7 +41274,7 @@ function ensureCurl() {
40935
41274
  }
40936
41275
  if (plat === "darwin") {
40937
41276
  try {
40938
- execSync27("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
41277
+ execSync28("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
40939
41278
  if (hasCmd("curl"))
40940
41279
  return true;
40941
41280
  } catch {
@@ -40970,7 +41309,7 @@ function installOllamaLinux() {
40970
41309
 
40971
41310
  `);
40972
41311
  try {
40973
- execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
41312
+ execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
40974
41313
  stdio: "inherit",
40975
41314
  timeout: 3e5
40976
41315
  });
@@ -40998,10 +41337,10 @@ async function installOllamaMac(_rl) {
40998
41337
 
40999
41338
  `);
41000
41339
  try {
41001
- execSync27('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
41340
+ execSync28('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
41002
41341
  if (!hasCmd("brew")) {
41003
41342
  try {
41004
- const brewPrefix = existsSync37("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
41343
+ const brewPrefix = existsSync38("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
41005
41344
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
41006
41345
  } catch {
41007
41346
  }
@@ -41031,7 +41370,7 @@ async function installOllamaMac(_rl) {
41031
41370
 
41032
41371
  `);
41033
41372
  try {
41034
- execSync27("brew install ollama", {
41373
+ execSync28("brew install ollama", {
41035
41374
  stdio: "inherit",
41036
41375
  timeout: 3e5
41037
41376
  });
@@ -41058,7 +41397,7 @@ function installOllamaWindows() {
41058
41397
 
41059
41398
  `);
41060
41399
  try {
41061
- execSync27('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
41400
+ execSync28('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
41062
41401
  stdio: "inherit",
41063
41402
  timeout: 3e5
41064
41403
  });
@@ -41109,7 +41448,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
41109
41448
  process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
41110
41449
  `);
41111
41450
  try {
41112
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
41451
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41113
41452
  child.unref();
41114
41453
  } catch {
41115
41454
  process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
@@ -41139,7 +41478,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
41139
41478
  }
41140
41479
  function pullModelWithAutoUpdate(tag) {
41141
41480
  try {
41142
- execSync27(`ollama pull ${tag}`, {
41481
+ execSync28(`ollama pull ${tag}`, {
41143
41482
  stdio: "inherit",
41144
41483
  timeout: 36e5
41145
41484
  // 1 hour max
@@ -41159,7 +41498,7 @@ function pullModelWithAutoUpdate(tag) {
41159
41498
 
41160
41499
  `);
41161
41500
  try {
41162
- execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
41501
+ execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
41163
41502
  stdio: "inherit",
41164
41503
  timeout: 3e5
41165
41504
  // 5 min max for install
@@ -41170,7 +41509,7 @@ function pullModelWithAutoUpdate(tag) {
41170
41509
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
41171
41510
 
41172
41511
  `);
41173
- execSync27(`ollama pull ${tag}`, {
41512
+ execSync28(`ollama pull ${tag}`, {
41174
41513
  stdio: "inherit",
41175
41514
  timeout: 36e5
41176
41515
  });
@@ -41272,7 +41611,7 @@ function ensurePython3() {
41272
41611
  if (plat === "darwin") {
41273
41612
  if (hasCmd("brew")) {
41274
41613
  try {
41275
- execSync27("brew install python3", { stdio: "inherit", timeout: 3e5 });
41614
+ execSync28("brew install python3", { stdio: "inherit", timeout: 3e5 });
41276
41615
  if (hasCmd("python3")) {
41277
41616
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
41278
41617
  `);
@@ -41285,7 +41624,7 @@ function ensurePython3() {
41285
41624
  for (const s of strategies) {
41286
41625
  if (hasCmd(s.check)) {
41287
41626
  try {
41288
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
41627
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
41289
41628
  if (hasCmd("python3") || hasCmd("python")) {
41290
41629
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
41291
41630
  `);
@@ -41301,11 +41640,11 @@ function ensurePython3() {
41301
41640
  }
41302
41641
  function checkPythonVenv() {
41303
41642
  try {
41304
- execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
41643
+ execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
41305
41644
  return true;
41306
41645
  } catch {
41307
41646
  try {
41308
- execSync27("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
41647
+ execSync28("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
41309
41648
  return true;
41310
41649
  } catch {
41311
41650
  return false;
@@ -41324,7 +41663,7 @@ function ensurePythonVenv() {
41324
41663
  for (const s of strategies) {
41325
41664
  if (hasCmd(s.check)) {
41326
41665
  try {
41327
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
41666
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
41328
41667
  if (checkPythonVenv()) {
41329
41668
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
41330
41669
  `);
@@ -41482,6 +41821,20 @@ async function doSetup(config, rl) {
41482
41821
  } else {
41483
41822
  process.stdout.write(` ${c2.dim(" GPU:")} No NVIDIA GPU detected (CPU inference)
41484
41823
  `);
41824
+ }
41825
+ let personaPlexCapable = false;
41826
+ try {
41827
+ const { detectPersonaPlexCapability: detectPersonaPlexCapability2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
41828
+ const ppCaps = detectPersonaPlexCapability2();
41829
+ personaPlexCapable = ppCaps.supported;
41830
+ if (ppCaps.supported) {
41831
+ process.stdout.write(` ${c2.green("\u2714")} PersonaPlex full-duplex voice: ${c2.bold("compatible")} (${ppCaps.gpuName}, ${ppCaps.vramGB.toFixed(0)}GB VRAM)
41832
+ `);
41833
+ process.stdout.write(` ${c2.dim("Enable with: /voice personaplex")}
41834
+
41835
+ `);
41836
+ }
41837
+ } catch {
41485
41838
  }
41486
41839
  const score = computeInferenceScore(specs);
41487
41840
  const bw = 30;
@@ -41571,7 +41924,7 @@ async function doSetup(config, rl) {
41571
41924
  ${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
41572
41925
  `);
41573
41926
  try {
41574
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
41927
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41575
41928
  child.unref();
41576
41929
  await new Promise((resolve36) => setTimeout(resolve36, 3e3));
41577
41930
  try {
@@ -41599,7 +41952,7 @@ async function doSetup(config, rl) {
41599
41952
  ${c2.cyan("\u25CF")} Starting ollama serve...
41600
41953
  `);
41601
41954
  try {
41602
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
41955
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41603
41956
  child.unref();
41604
41957
  await new Promise((resolve36) => setTimeout(resolve36, 3e3));
41605
41958
  try {
@@ -41732,12 +42085,12 @@ async function doSetup(config, rl) {
41732
42085
  `PARAMETER num_predict ${numPredict}`,
41733
42086
  `PARAMETER stop "<|endoftext|>"`
41734
42087
  ].join("\n");
41735
- const modelDir2 = join54(homedir13(), ".open-agents", "models");
41736
- mkdirSync15(modelDir2, { recursive: true });
41737
- const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
41738
- writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
42088
+ const modelDir2 = join55(homedir14(), ".open-agents", "models");
42089
+ mkdirSync16(modelDir2, { recursive: true });
42090
+ const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
42091
+ writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
41739
42092
  process.stdout.write(` ${c2.dim("Creating model...")} `);
41740
- execSync27(`ollama create ${customName} -f ${modelfilePath}`, {
42093
+ execSync28(`ollama create ${customName} -f ${modelfilePath}`, {
41741
42094
  stdio: "pipe",
41742
42095
  timeout: 12e4
41743
42096
  });
@@ -41780,7 +42133,7 @@ async function isModelAvailable(config) {
41780
42133
  }
41781
42134
  function isFirstRun() {
41782
42135
  try {
41783
- return !existsSync37(join54(homedir13(), ".open-agents", "config.json"));
42136
+ return !existsSync38(join55(homedir14(), ".open-agents", "config.json"));
41784
42137
  } catch {
41785
42138
  return true;
41786
42139
  }
@@ -41788,7 +42141,7 @@ function isFirstRun() {
41788
42141
  function hasCmd(cmd) {
41789
42142
  try {
41790
42143
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
41791
- execSync27(whichCmd, { stdio: "pipe", timeout: 3e3 });
42144
+ execSync28(whichCmd, { stdio: "pipe", timeout: 3e3 });
41792
42145
  return true;
41793
42146
  } catch {
41794
42147
  return false;
@@ -41817,11 +42170,11 @@ function detectPkgManager() {
41817
42170
  return null;
41818
42171
  }
41819
42172
  function getVenvDir() {
41820
- return join54(homedir13(), ".open-agents", "venv");
42173
+ return join55(homedir14(), ".open-agents", "venv");
41821
42174
  }
41822
42175
  function hasVenvModule() {
41823
42176
  try {
41824
- execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
42177
+ execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
41825
42178
  return true;
41826
42179
  } catch {
41827
42180
  return false;
@@ -41830,9 +42183,9 @@ function hasVenvModule() {
41830
42183
  function ensureVenv(log) {
41831
42184
  const venvDir = getVenvDir();
41832
42185
  const isWin2 = process.platform === "win32";
41833
- const pipPath = isWin2 ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
42186
+ const pipPath = isWin2 ? join55(venvDir, "Scripts", "pip.exe") : join55(venvDir, "bin", "pip");
41834
42187
  const pythonCmd = isWin2 ? "python" : "python3";
41835
- if (existsSync37(pipPath))
42188
+ if (existsSync38(pipPath))
41836
42189
  return venvDir;
41837
42190
  log("Creating Python venv for vision deps...");
41838
42191
  if (!hasCmd(pythonCmd) && !hasCmd("python3")) {
@@ -41844,10 +42197,10 @@ function ensureVenv(log) {
41844
42197
  return null;
41845
42198
  }
41846
42199
  try {
41847
- mkdirSync15(join54(homedir13(), ".open-agents"), { recursive: true });
42200
+ mkdirSync16(join55(homedir14(), ".open-agents"), { recursive: true });
41848
42201
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
41849
- execSync27(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
41850
- execSync27(`"${pipPath}" install --upgrade pip`, {
42202
+ execSync28(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
42203
+ execSync28(`"${pipPath}" install --upgrade pip`, {
41851
42204
  stdio: "pipe",
41852
42205
  timeout: 6e4
41853
42206
  });
@@ -41860,7 +42213,7 @@ function ensureVenv(log) {
41860
42213
  }
41861
42214
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
41862
42215
  try {
41863
- execSync27(`sudo -n ${cmd}`, {
42216
+ execSync28(`sudo -n ${cmd}`, {
41864
42217
  stdio: "pipe",
41865
42218
  timeout: timeoutMs,
41866
42219
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -41873,7 +42226,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
41873
42226
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
41874
42227
  try {
41875
42228
  const escaped = cmd.replace(/'/g, "'\\''");
41876
- execSync27(`sudo -S bash -c '${escaped}'`, {
42229
+ execSync28(`sudo -S bash -c '${escaped}'`, {
41877
42230
  input: password + "\n",
41878
42231
  stdio: ["pipe", "pipe", "pipe"],
41879
42232
  timeout: timeoutMs,
@@ -41990,7 +42343,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
41990
42343
  ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
41991
42344
  } else {
41992
42345
  try {
41993
- execSync27(batchCmd, { stdio: "pipe", timeout: 18e4 });
42346
+ execSync28(batchCmd, { stdio: "pipe", timeout: 18e4 });
41994
42347
  ok = true;
41995
42348
  } catch {
41996
42349
  ok = false;
@@ -42027,7 +42380,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42027
42380
  const venvCmds = {
42028
42381
  apt: () => {
42029
42382
  try {
42030
- const pyVer = execSync27(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
42383
+ const pyVer = execSync28(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
42031
42384
  return `apt-get install -y python3-venv python${pyVer}-venv`;
42032
42385
  } catch {
42033
42386
  return "apt-get install -y python3-venv";
@@ -42048,19 +42401,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42048
42401
  }
42049
42402
  }
42050
42403
  const venvDir = getVenvDir();
42051
- const venvBin = join54(venvDir, "bin");
42052
- const venvMoondream = join54(venvBin, "moondream-station");
42404
+ const venvBin = join55(venvDir, "bin");
42405
+ const venvMoondream = join55(venvBin, "moondream-station");
42053
42406
  const venv = ensureVenv(log);
42054
- if (venv && !hasCmd("moondream-station") && !existsSync37(venvMoondream)) {
42055
- const venvPip2 = join54(venvBin, "pip");
42407
+ if (venv && !hasCmd("moondream-station") && !existsSync38(venvMoondream)) {
42408
+ const venvPip2 = join55(venvBin, "pip");
42056
42409
  log("Installing moondream-station in ~/.open-agents/venv...");
42057
42410
  try {
42058
- execSync27(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
42059
- if (existsSync37(venvMoondream)) {
42411
+ execSync28(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
42412
+ if (existsSync38(venvMoondream)) {
42060
42413
  log("moondream-station installed successfully.");
42061
42414
  } else {
42062
42415
  try {
42063
- const check = execSync27(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
42416
+ const check = execSync28(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
42064
42417
  if (check.includes("moondream")) {
42065
42418
  log("moondream-station package installed.");
42066
42419
  }
@@ -42073,11 +42426,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42073
42426
  }
42074
42427
  }
42075
42428
  if (venv) {
42076
- const venvPython2 = join54(venvBin, "python");
42077
- const venvPip2 = join54(venvBin, "pip");
42429
+ const venvPython2 = join55(venvBin, "python");
42430
+ const venvPip2 = join55(venvBin, "pip");
42078
42431
  let ocrStackInstalled = false;
42079
42432
  try {
42080
- execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42433
+ execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42081
42434
  ocrStackInstalled = true;
42082
42435
  } catch {
42083
42436
  }
@@ -42085,9 +42438,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42085
42438
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
42086
42439
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
42087
42440
  try {
42088
- execSync27(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
42441
+ execSync28(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
42089
42442
  try {
42090
- execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42443
+ execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42091
42444
  log("OCR Python stack installed successfully.");
42092
42445
  } catch {
42093
42446
  log("OCR Python stack install completed but import verification failed.");
@@ -42121,9 +42474,9 @@ function ensureCloudflaredBackground(onInfo) {
42121
42474
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
42122
42475
  const cfArch = archMap[arch2] ?? "amd64";
42123
42476
  try {
42124
- execSync27(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir13()}/.local/bin" && mv /tmp/cloudflared "${homedir13()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
42125
- if (!process.env.PATH?.includes(`${homedir13()}/.local/bin`)) {
42126
- process.env.PATH = `${homedir13()}/.local/bin:${process.env.PATH}`;
42477
+ execSync28(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir14()}/.local/bin" && mv /tmp/cloudflared "${homedir14()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
42478
+ if (!process.env.PATH?.includes(`${homedir14()}/.local/bin`)) {
42479
+ process.env.PATH = `${homedir14()}/.local/bin:${process.env.PATH}`;
42127
42480
  }
42128
42481
  if (hasCmd("cloudflared")) {
42129
42482
  log("cloudflared installed.");
@@ -42132,7 +42485,7 @@ function ensureCloudflaredBackground(onInfo) {
42132
42485
  } catch {
42133
42486
  }
42134
42487
  try {
42135
- execSync27(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
42488
+ execSync28(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
42136
42489
  if (hasCmd("cloudflared")) {
42137
42490
  log("cloudflared installed.");
42138
42491
  return true;
@@ -42141,7 +42494,7 @@ function ensureCloudflaredBackground(onInfo) {
42141
42494
  }
42142
42495
  } else if (os === "darwin") {
42143
42496
  try {
42144
- execSync27("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
42497
+ execSync28("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
42145
42498
  if (hasCmd("cloudflared")) {
42146
42499
  log("cloudflared installed via Homebrew.");
42147
42500
  return true;
@@ -42218,10 +42571,10 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
42218
42571
  `PARAMETER num_predict ${numPredict}`,
42219
42572
  `PARAMETER stop "<|endoftext|>"`
42220
42573
  ].join("\n");
42221
- const modelDir2 = join54(homedir13(), ".open-agents", "models");
42222
- mkdirSync15(modelDir2, { recursive: true });
42223
- const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
42224
- writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
42574
+ const modelDir2 = join55(homedir14(), ".open-agents", "models");
42575
+ mkdirSync16(modelDir2, { recursive: true });
42576
+ const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
42577
+ writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
42225
42578
  await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
42226
42579
  timeout: 12e4
42227
42580
  });
@@ -42283,7 +42636,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
42283
42636
  }
42284
42637
  async function ensureNeovim() {
42285
42638
  try {
42286
- const nvimPath = execSync27("which nvim 2>/dev/null || where nvim 2>nul", {
42639
+ const nvimPath = execSync28("which nvim 2>/dev/null || where nvim 2>nul", {
42287
42640
  encoding: "utf8",
42288
42641
  stdio: "pipe",
42289
42642
  timeout: 5e3
@@ -42295,24 +42648,24 @@ async function ensureNeovim() {
42295
42648
  const platform6 = process.platform;
42296
42649
  const arch2 = process.arch;
42297
42650
  if (platform6 === "linux") {
42298
- const binDir = join54(homedir13(), ".local", "bin");
42299
- const nvimDest = join54(binDir, "nvim");
42651
+ const binDir = join55(homedir14(), ".local", "bin");
42652
+ const nvimDest = join55(binDir, "nvim");
42300
42653
  try {
42301
- mkdirSync15(binDir, { recursive: true });
42654
+ mkdirSync16(binDir, { recursive: true });
42302
42655
  } catch {
42303
42656
  }
42304
42657
  const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
42305
42658
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
42306
42659
  console.log(` Downloading Neovim (${appImageName})...`);
42307
42660
  try {
42308
- execSync27(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
42309
- execSync27(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
42661
+ execSync28(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
42662
+ execSync28(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
42310
42663
  } catch (err) {
42311
42664
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
42312
42665
  return null;
42313
42666
  }
42314
42667
  try {
42315
- const ver = execSync27(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
42668
+ const ver = execSync28(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
42316
42669
  console.log(` Installed: ${ver}`);
42317
42670
  } catch {
42318
42671
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -42327,8 +42680,8 @@ async function ensureNeovim() {
42327
42680
  if (hasCmd("brew")) {
42328
42681
  console.log(" Installing Neovim via Homebrew...");
42329
42682
  try {
42330
- execSync27("brew install neovim", { stdio: "inherit", timeout: 12e4 });
42331
- const nvimPath = execSync27("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
42683
+ execSync28("brew install neovim", { stdio: "inherit", timeout: 12e4 });
42684
+ const nvimPath = execSync28("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
42332
42685
  return nvimPath || null;
42333
42686
  } catch {
42334
42687
  console.log(" brew install neovim failed.");
@@ -42342,7 +42695,7 @@ async function ensureNeovim() {
42342
42695
  if (hasCmd("choco")) {
42343
42696
  console.log(" Installing Neovim via Chocolatey...");
42344
42697
  try {
42345
- execSync27("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
42698
+ execSync28("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
42346
42699
  return "nvim";
42347
42700
  } catch {
42348
42701
  console.log(" choco install neovim failed.");
@@ -42351,7 +42704,7 @@ async function ensureNeovim() {
42351
42704
  if (hasCmd("winget")) {
42352
42705
  console.log(" Installing Neovim via winget...");
42353
42706
  try {
42354
- execSync27("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
42707
+ execSync28("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
42355
42708
  stdio: "inherit",
42356
42709
  timeout: 12e4
42357
42710
  });
@@ -42367,9 +42720,9 @@ async function ensureNeovim() {
42367
42720
  }
42368
42721
  function ensurePathInShellRc(binDir) {
42369
42722
  const shell = process.env.SHELL ?? "";
42370
- const rcFile = shell.includes("zsh") ? join54(homedir13(), ".zshrc") : join54(homedir13(), ".bashrc");
42723
+ const rcFile = shell.includes("zsh") ? join55(homedir14(), ".zshrc") : join55(homedir14(), ".bashrc");
42371
42724
  try {
42372
- const rcContent = existsSync37(rcFile) ? readFileSync28(rcFile, "utf8") : "";
42725
+ const rcContent = existsSync38(rcFile) ? readFileSync29(rcFile, "utf8") : "";
42373
42726
  if (rcContent.includes(binDir))
42374
42727
  return;
42375
42728
  const exportLine = `
@@ -42407,7 +42760,7 @@ var init_setup = __esm({
42407
42760
  });
42408
42761
 
42409
42762
  // packages/cli/dist/tui/drop-panel.js
42410
- import { existsSync as existsSync38 } from "node:fs";
42763
+ import { existsSync as existsSync39 } from "node:fs";
42411
42764
  import { extname as extname10, resolve as resolve29 } from "node:path";
42412
42765
  function ansi4(code, text) {
42413
42766
  return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
@@ -42522,7 +42875,7 @@ function showDropPanel(opts) {
42522
42875
  filePath = decodeURIComponent(filePath.slice(7));
42523
42876
  }
42524
42877
  filePath = resolve29(filePath);
42525
- if (!existsSync38(filePath)) {
42878
+ if (!existsSync39(filePath)) {
42526
42879
  errorMsg = `File not found: ${filePath}`;
42527
42880
  render();
42528
42881
  return;
@@ -42593,10 +42946,10 @@ var init_drop_panel = __esm({
42593
42946
  });
42594
42947
 
42595
42948
  // packages/cli/dist/tui/neovim-mode.js
42596
- import { existsSync as existsSync39, unlinkSync as unlinkSync8 } from "node:fs";
42949
+ import { existsSync as existsSync40, unlinkSync as unlinkSync8 } from "node:fs";
42597
42950
  import { tmpdir as tmpdir8 } from "node:os";
42598
- import { join as join55 } from "node:path";
42599
- import { execSync as execSync28 } from "node:child_process";
42951
+ import { join as join56 } from "node:path";
42952
+ import { execSync as execSync29 } from "node:child_process";
42600
42953
  function isNeovimActive() {
42601
42954
  return _state !== null && !_state.cleanedUp;
42602
42955
  }
@@ -42614,7 +42967,7 @@ async function startNeovimMode(opts) {
42614
42967
  }
42615
42968
  let nvimPath;
42616
42969
  try {
42617
- nvimPath = execSync28("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
42970
+ nvimPath = execSync29("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
42618
42971
  if (!nvimPath)
42619
42972
  throw new Error();
42620
42973
  } catch {
@@ -42643,9 +42996,9 @@ async function startNeovimMode(opts) {
42643
42996
  );
42644
42997
  } catch {
42645
42998
  }
42646
- const socketPath = join55(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
42999
+ const socketPath = join56(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
42647
43000
  try {
42648
- if (existsSync39(socketPath))
43001
+ if (existsSync40(socketPath))
42649
43002
  unlinkSync8(socketPath);
42650
43003
  } catch {
42651
43004
  }
@@ -42872,13 +43225,13 @@ function resizeNeovim(cols, contentRows) {
42872
43225
  }
42873
43226
  async function connectRPC(state, neovimPkg, cols) {
42874
43227
  let attempts = 0;
42875
- while (!existsSync39(state.socketPath) && attempts < 30) {
43228
+ while (!existsSync40(state.socketPath) && attempts < 30) {
42876
43229
  await new Promise((r) => setTimeout(r, 200));
42877
43230
  attempts++;
42878
43231
  if (state.cleanedUp)
42879
43232
  return;
42880
43233
  }
42881
- if (!existsSync39(state.socketPath))
43234
+ if (!existsSync40(state.socketPath))
42882
43235
  return;
42883
43236
  const nvim = neovimPkg.attach({ socket: state.socketPath });
42884
43237
  state.nvim = nvim;
@@ -43015,7 +43368,7 @@ function doCleanup(state) {
43015
43368
  state.pty = null;
43016
43369
  }
43017
43370
  try {
43018
- if (existsSync39(state.socketPath))
43371
+ if (existsSync40(state.socketPath))
43019
43372
  unlinkSync8(state.socketPath);
43020
43373
  } catch {
43021
43374
  }
@@ -43450,8 +43803,8 @@ __export(sponsor_wizard_exports, {
43450
43803
  saveSponsorConfig: () => saveSponsorConfig,
43451
43804
  showSponsorDashboard: () => showSponsorDashboard
43452
43805
  });
43453
- import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync16 } from "node:fs";
43454
- import { join as join56 } from "node:path";
43806
+ import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17 } from "node:fs";
43807
+ import { join as join57 } from "node:path";
43455
43808
  function colorPreview(code) {
43456
43809
  return `\x1B[38;5;${code}m\u2588\u2588\u2588\u2588\x1B[0m (${code})`;
43457
43810
  }
@@ -43464,26 +43817,26 @@ function gradientPreview(start, end) {
43464
43817
  return s;
43465
43818
  }
43466
43819
  function sponsorDir(projectDir) {
43467
- return join56(projectDir, ".oa", "sponsor");
43820
+ return join57(projectDir, ".oa", "sponsor");
43468
43821
  }
43469
43822
  function configPath(projectDir) {
43470
- return join56(sponsorDir(projectDir), "config.json");
43823
+ return join57(sponsorDir(projectDir), "config.json");
43471
43824
  }
43472
43825
  function loadSponsorConfig(projectDir) {
43473
43826
  const p = configPath(projectDir);
43474
- if (!existsSync40(p))
43827
+ if (!existsSync41(p))
43475
43828
  return null;
43476
43829
  try {
43477
- return JSON.parse(readFileSync29(p, "utf8"));
43830
+ return JSON.parse(readFileSync30(p, "utf8"));
43478
43831
  } catch {
43479
43832
  return null;
43480
43833
  }
43481
43834
  }
43482
43835
  function saveSponsorConfig(projectDir, config) {
43483
43836
  const dir = sponsorDir(projectDir);
43484
- mkdirSync16(dir, { recursive: true });
43837
+ mkdirSync17(dir, { recursive: true });
43485
43838
  config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
43486
- writeFileSync17(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
43839
+ writeFileSync18(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
43487
43840
  }
43488
43841
  function defaultConfig() {
43489
43842
  return {
@@ -44186,10 +44539,10 @@ __export(voice_exports, {
44186
44539
  registerCustomOnnxModel: () => registerCustomOnnxModel,
44187
44540
  resetNarrationContext: () => resetNarrationContext
44188
44541
  });
44189
- 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";
44190
- import { join as join57, dirname as dirname18 } from "node:path";
44191
- import { homedir as homedir14, tmpdir as tmpdir9, platform as platform3 } from "node:os";
44192
- import { execSync as execSync29, spawn as nodeSpawn } from "node:child_process";
44542
+ import { existsSync as existsSync42, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, readFileSync as readFileSync31, unlinkSync as unlinkSync9, readdirSync as readdirSync11, renameSync, statSync as statSync13 } from "node:fs";
44543
+ import { join as join58, dirname as dirname18 } from "node:path";
44544
+ import { homedir as homedir15, tmpdir as tmpdir9, platform as platform3 } from "node:os";
44545
+ import { execSync as execSync30, spawn as nodeSpawn } from "node:child_process";
44193
44546
  import { createRequire } from "node:module";
44194
44547
  function sanitizeForTTS(text) {
44195
44548
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
@@ -44212,40 +44565,40 @@ function listVoiceModels() {
44212
44565
  }));
44213
44566
  }
44214
44567
  function voiceDir() {
44215
- return join57(homedir14(), ".open-agents", "voice");
44568
+ return join58(homedir15(), ".open-agents", "voice");
44216
44569
  }
44217
44570
  function modelsDir() {
44218
- return join57(voiceDir(), "models");
44571
+ return join58(voiceDir(), "models");
44219
44572
  }
44220
44573
  function modelDir(id) {
44221
- return join57(modelsDir(), id);
44574
+ return join58(modelsDir(), id);
44222
44575
  }
44223
44576
  function modelOnnxPath(id) {
44224
- return join57(modelDir(id), "model.onnx");
44577
+ return join58(modelDir(id), "model.onnx");
44225
44578
  }
44226
44579
  function modelConfigPath(id) {
44227
- return join57(modelDir(id), "config.json");
44580
+ return join58(modelDir(id), "config.json");
44228
44581
  }
44229
44582
  function luxttsVenvDir() {
44230
- return join57(voiceDir(), "luxtts-venv");
44583
+ return join58(voiceDir(), "luxtts-venv");
44231
44584
  }
44232
44585
  function luxttsVenvPy() {
44233
- return platform3() === "win32" ? join57(luxttsVenvDir(), "Scripts", "python.exe") : join57(luxttsVenvDir(), "bin", "python3");
44586
+ return platform3() === "win32" ? join58(luxttsVenvDir(), "Scripts", "python.exe") : join58(luxttsVenvDir(), "bin", "python3");
44234
44587
  }
44235
44588
  function luxttsRepoDir() {
44236
- return join57(voiceDir(), "LuxTTS");
44589
+ return join58(voiceDir(), "LuxTTS");
44237
44590
  }
44238
44591
  function luxttsCloneRefsDir() {
44239
- return join57(voiceDir(), "clone-refs");
44592
+ return join58(voiceDir(), "clone-refs");
44240
44593
  }
44241
44594
  function luxttsInferScript() {
44242
- return join57(voiceDir(), "luxtts-infer.py");
44595
+ return join58(voiceDir(), "luxtts-infer.py");
44243
44596
  }
44244
44597
  function writeDetectTorchScript(targetPath) {
44245
- if (existsSync41(targetPath))
44598
+ if (existsSync42(targetPath))
44246
44599
  return;
44247
44600
  try {
44248
- mkdirSync17(dirname18(targetPath), { recursive: true });
44601
+ mkdirSync18(dirname18(targetPath), { recursive: true });
44249
44602
  } catch {
44250
44603
  }
44251
44604
  const script = `#!/usr/bin/env python3
@@ -44318,7 +44671,7 @@ def main():
44318
44671
  if __name__ == "__main__": main()
44319
44672
  `;
44320
44673
  try {
44321
- writeFileSync18(targetPath, script, { mode: 493 });
44674
+ writeFileSync19(targetPath, script, { mode: 493 });
44322
44675
  } catch {
44323
44676
  }
44324
44677
  }
@@ -45128,8 +45481,8 @@ var init_voice = __esm({
45128
45481
  const refsDir = luxttsCloneRefsDir();
45129
45482
  const targets = ["glados", "overwatch"];
45130
45483
  for (const modelId of targets) {
45131
- const refFile = join57(refsDir, `${modelId}-ref.wav`);
45132
- if (existsSync41(refFile))
45484
+ const refFile = join58(refsDir, `${modelId}-ref.wav`);
45485
+ if (existsSync42(refFile))
45133
45486
  continue;
45134
45487
  try {
45135
45488
  await this.generateCloneRef(modelId);
@@ -45208,24 +45561,24 @@ var init_voice = __esm({
45208
45561
  }
45209
45562
  p = p.replace(/\\ /g, " ");
45210
45563
  if (p.startsWith("~/") || p === "~") {
45211
- p = join57(homedir14(), p.slice(1));
45564
+ p = join58(homedir15(), p.slice(1));
45212
45565
  }
45213
- if (!existsSync41(p)) {
45566
+ if (!existsSync42(p)) {
45214
45567
  return `File not found: ${p}
45215
45568
  (original input: ${audioPath})`;
45216
45569
  }
45217
45570
  audioPath = p;
45218
45571
  const refsDir = luxttsCloneRefsDir();
45219
- if (!existsSync41(refsDir))
45220
- mkdirSync17(refsDir, { recursive: true });
45572
+ if (!existsSync42(refsDir))
45573
+ mkdirSync18(refsDir, { recursive: true });
45221
45574
  const ext = audioPath.split(".").pop() || "wav";
45222
45575
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
45223
45576
  const ts = Date.now().toString(36);
45224
45577
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
45225
- const destPath = join57(refsDir, destFilename);
45578
+ const destPath = join58(refsDir, destFilename);
45226
45579
  try {
45227
- const data = readFileSync30(audioPath);
45228
- writeFileSync18(destPath, data);
45580
+ const data = readFileSync31(audioPath);
45581
+ writeFileSync19(destPath, data);
45229
45582
  } catch (err) {
45230
45583
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
45231
45584
  }
@@ -45265,9 +45618,9 @@ var init_voice = __esm({
45265
45618
  return `Failed to synthesize reference audio from ${source.label}.`;
45266
45619
  }
45267
45620
  const refsDir = luxttsCloneRefsDir();
45268
- if (!existsSync41(refsDir))
45269
- mkdirSync17(refsDir, { recursive: true });
45270
- const destPath = join57(refsDir, `${sourceModelId}-ref.wav`);
45621
+ if (!existsSync42(refsDir))
45622
+ mkdirSync18(refsDir, { recursive: true });
45623
+ const destPath = join58(refsDir, `${sourceModelId}-ref.wav`);
45271
45624
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
45272
45625
  this.writeWav(audioData, sampleRate, destPath);
45273
45626
  this.luxttsCloneRef = destPath;
@@ -45283,23 +45636,23 @@ var init_voice = __esm({
45283
45636
  // -------------------------------------------------------------------------
45284
45637
  /** Metadata file for friendly names of clone refs */
45285
45638
  static cloneMetaFile() {
45286
- return join57(luxttsCloneRefsDir(), "meta.json");
45639
+ return join58(luxttsCloneRefsDir(), "meta.json");
45287
45640
  }
45288
45641
  loadCloneMeta() {
45289
45642
  const p = _VoiceEngine.cloneMetaFile();
45290
- if (!existsSync41(p))
45643
+ if (!existsSync42(p))
45291
45644
  return {};
45292
45645
  try {
45293
- return JSON.parse(readFileSync30(p, "utf8"));
45646
+ return JSON.parse(readFileSync31(p, "utf8"));
45294
45647
  } catch {
45295
45648
  return {};
45296
45649
  }
45297
45650
  }
45298
45651
  saveCloneMeta(meta) {
45299
45652
  const dir = luxttsCloneRefsDir();
45300
- if (!existsSync41(dir))
45301
- mkdirSync17(dir, { recursive: true });
45302
- writeFileSync18(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
45653
+ if (!existsSync42(dir))
45654
+ mkdirSync18(dir, { recursive: true });
45655
+ writeFileSync19(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
45303
45656
  }
45304
45657
  /** Audio file extensions recognized as clone references */
45305
45658
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -45309,7 +45662,7 @@ var init_voice = __esm({
45309
45662
  */
45310
45663
  listCloneRefs() {
45311
45664
  const dir = luxttsCloneRefsDir();
45312
- if (!existsSync41(dir))
45665
+ if (!existsSync42(dir))
45313
45666
  return [];
45314
45667
  const meta = this.loadCloneMeta();
45315
45668
  const files = readdirSync11(dir).filter((f) => {
@@ -45317,7 +45670,7 @@ var init_voice = __esm({
45317
45670
  return _VoiceEngine.AUDIO_EXTS.has(ext);
45318
45671
  });
45319
45672
  return files.map((f) => {
45320
- const p = join57(dir, f);
45673
+ const p = join58(dir, f);
45321
45674
  let size = 0;
45322
45675
  try {
45323
45676
  size = statSync13(p).size;
@@ -45334,8 +45687,8 @@ var init_voice = __esm({
45334
45687
  }
45335
45688
  /** Delete a clone reference file by filename. Returns true if deleted. */
45336
45689
  deleteCloneRef(filename) {
45337
- const p = join57(luxttsCloneRefsDir(), filename);
45338
- if (!existsSync41(p))
45690
+ const p = join58(luxttsCloneRefsDir(), filename);
45691
+ if (!existsSync42(p))
45339
45692
  return false;
45340
45693
  try {
45341
45694
  unlinkSync9(p);
@@ -45359,8 +45712,8 @@ var init_voice = __esm({
45359
45712
  }
45360
45713
  /** Set the active clone reference by filename. */
45361
45714
  setActiveCloneRef(filename) {
45362
- const p = join57(luxttsCloneRefsDir(), filename);
45363
- if (!existsSync41(p))
45715
+ const p = join58(luxttsCloneRefsDir(), filename);
45716
+ if (!existsSync42(p))
45364
45717
  return `File not found: ${filename}`;
45365
45718
  this.luxttsCloneRef = p;
45366
45719
  return `Active clone voice set to: ${filename}`;
@@ -45685,7 +46038,7 @@ var init_voice = __esm({
45685
46038
  }
45686
46039
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
45687
46040
  }
45688
- const wavPath = join57(tmpdir9(), `oa-voice-${Date.now()}.wav`);
46041
+ const wavPath = join58(tmpdir9(), `oa-voice-${Date.now()}.wav`);
45689
46042
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
45690
46043
  await this.playWav(wavPath);
45691
46044
  try {
@@ -45802,7 +46155,7 @@ var init_voice = __esm({
45802
46155
  buffer.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
45803
46156
  pos += 2;
45804
46157
  }
45805
- writeFileSync18(path, buffer);
46158
+ writeFileSync19(path, buffer);
45806
46159
  }
45807
46160
  // -------------------------------------------------------------------------
45808
46161
  // Phonemization
@@ -45880,7 +46233,7 @@ var init_voice = __esm({
45880
46233
  return buffer;
45881
46234
  }
45882
46235
  writeWav(samples, sampleRate, path) {
45883
- writeFileSync18(path, this.buildWavBuffer(samples, sampleRate));
46236
+ writeFileSync19(path, this.buildWavBuffer(samples, sampleRate));
45884
46237
  }
45885
46238
  // -------------------------------------------------------------------------
45886
46239
  // Audio playback (system default speakers)
@@ -45930,7 +46283,7 @@ var init_voice = __esm({
45930
46283
  }
45931
46284
  for (const player of ["paplay", "pw-play", "aplay"]) {
45932
46285
  try {
45933
- execSync29(`which ${player}`, { stdio: "pipe" });
46286
+ execSync30(`which ${player}`, { stdio: "pipe" });
45934
46287
  return [player, path];
45935
46288
  } catch {
45936
46289
  }
@@ -45959,7 +46312,7 @@ var init_voice = __esm({
45959
46312
  return this.python3Path;
45960
46313
  for (const bin of ["python3", "python"]) {
45961
46314
  try {
45962
- const path = execSync29(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
46315
+ const path = execSync30(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
45963
46316
  if (path) {
45964
46317
  this.python3Path = path;
45965
46318
  return path;
@@ -46025,7 +46378,7 @@ var init_voice = __esm({
46025
46378
  return false;
46026
46379
  }
46027
46380
  try {
46028
- execSync29(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
46381
+ execSync30(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
46029
46382
  this.mlxInstalled = true;
46030
46383
  return true;
46031
46384
  } catch {
@@ -46078,7 +46431,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46078
46431
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
46079
46432
  const mlxVoice = model.mlxVoice ?? "af_heart";
46080
46433
  const mlxLangCode = model.mlxLangCode ?? "a";
46081
- const wavPath = join57(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
46434
+ const wavPath = join58(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
46082
46435
  const pyScript = [
46083
46436
  "import sys, json",
46084
46437
  "from mlx_audio.tts import generate as tts_gen",
@@ -46086,20 +46439,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46086
46439
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
46087
46440
  ].join("; ");
46088
46441
  try {
46089
- execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46442
+ execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46090
46443
  } catch (err) {
46091
46444
  try {
46092
46445
  const safeText = cleaned.replace(/'/g, "'\\''");
46093
- execSync29(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46446
+ execSync30(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46094
46447
  } catch (err2) {
46095
46448
  return;
46096
46449
  }
46097
46450
  }
46098
- if (!existsSync41(wavPath))
46451
+ if (!existsSync42(wavPath))
46099
46452
  return;
46100
46453
  if (volume !== 1) {
46101
46454
  try {
46102
- const wavData = readFileSync30(wavPath);
46455
+ const wavData = readFileSync31(wavPath);
46103
46456
  if (wavData.length > 44) {
46104
46457
  const header = wavData.subarray(0, 44);
46105
46458
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -46107,14 +46460,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46107
46460
  samples[i] = Math.round(samples[i] * volume);
46108
46461
  }
46109
46462
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
46110
- writeFileSync18(wavPath, scaled);
46463
+ writeFileSync19(wavPath, scaled);
46111
46464
  }
46112
46465
  } catch {
46113
46466
  }
46114
46467
  }
46115
46468
  if (this.onPCMOutput) {
46116
46469
  try {
46117
- const wavData = readFileSync30(wavPath);
46470
+ const wavData = readFileSync31(wavPath);
46118
46471
  if (wavData.length > 44) {
46119
46472
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
46120
46473
  const sampleRate = wavData.readUInt32LE(24);
@@ -46146,7 +46499,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46146
46499
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
46147
46500
  const mlxVoice = model.mlxVoice ?? "af_heart";
46148
46501
  const mlxLangCode = model.mlxLangCode ?? "a";
46149
- const wavPath = join57(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
46502
+ const wavPath = join58(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
46150
46503
  const pyScript = [
46151
46504
  "import sys, json",
46152
46505
  "from mlx_audio.tts import generate as tts_gen",
@@ -46154,19 +46507,19 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46154
46507
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
46155
46508
  ].join("; ");
46156
46509
  try {
46157
- execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46510
+ execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46158
46511
  } catch {
46159
46512
  try {
46160
46513
  const safeText = cleaned.replace(/'/g, "'\\''");
46161
- execSync29(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46514
+ execSync30(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46162
46515
  } catch {
46163
46516
  return null;
46164
46517
  }
46165
46518
  }
46166
- if (!existsSync41(wavPath))
46519
+ if (!existsSync42(wavPath))
46167
46520
  return null;
46168
46521
  try {
46169
- const data = readFileSync30(wavPath);
46522
+ const data = readFileSync31(wavPath);
46170
46523
  unlinkSync9(wavPath);
46171
46524
  return data;
46172
46525
  } catch {
@@ -46189,7 +46542,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46189
46542
  }
46190
46543
  const venvDir = luxttsVenvDir();
46191
46544
  const venvPy = luxttsVenvPy();
46192
- if (existsSync41(venvPy)) {
46545
+ if (existsSync42(venvPy)) {
46193
46546
  try {
46194
46547
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
46195
46548
  let hasCudaSys = false;
@@ -46203,7 +46556,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46203
46556
  if (torchCheck === "cpu") {
46204
46557
  renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
46205
46558
  try {
46206
- const detectScript = join57(voiceDir(), "detect-torch.py");
46559
+ const detectScript = join58(voiceDir(), "detect-torch.py");
46207
46560
  writeDetectTorchScript(detectScript);
46208
46561
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
46209
46562
  try {
@@ -46228,7 +46581,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46228
46581
  }
46229
46582
  }
46230
46583
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
46231
- if (!existsSync41(venvDir)) {
46584
+ if (!existsSync42(venvDir)) {
46232
46585
  renderInfo(" Creating Python virtual environment...");
46233
46586
  try {
46234
46587
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -46237,7 +46590,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46237
46590
  }
46238
46591
  }
46239
46592
  {
46240
- const detectScript = join57(voiceDir(), "detect-torch.py");
46593
+ const detectScript = join58(voiceDir(), "detect-torch.py");
46241
46594
  writeDetectTorchScript(detectScript);
46242
46595
  let pipArgsStr = "torch torchaudio";
46243
46596
  let torchDesc = "unknown platform";
@@ -46274,10 +46627,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46274
46627
  }
46275
46628
  }
46276
46629
  const repoDir = luxttsRepoDir();
46277
- if (!existsSync41(join57(repoDir, "zipvoice", "luxvoice.py"))) {
46630
+ if (!existsSync42(join58(repoDir, "zipvoice", "luxvoice.py"))) {
46278
46631
  renderInfo(" Cloning LuxTTS repository...");
46279
46632
  try {
46280
- if (existsSync41(repoDir)) {
46633
+ if (existsSync42(repoDir)) {
46281
46634
  const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
46282
46635
  await this.asyncShell(rmCmd, 3e4);
46283
46636
  }
@@ -46356,7 +46709,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46356
46709
  renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
46357
46710
  }
46358
46711
  }
46359
- const isJetson = isArm && (existsSync41("/etc/nv_tegra_release") || existsSync41("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
46712
+ const isJetson = isArm && (existsSync42("/etc/nv_tegra_release") || existsSync42("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
46360
46713
  const installSteps = isArm ? [
46361
46714
  // ARM: install individually so we get clear error messages per package.
46362
46715
  // ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
@@ -46426,14 +46779,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46426
46779
  }
46427
46780
  /** Auto-detect an existing clone reference in the refs directory */
46428
46781
  autoDetectCloneRef() {
46429
- if (this.luxttsCloneRef && existsSync41(this.luxttsCloneRef))
46782
+ if (this.luxttsCloneRef && existsSync42(this.luxttsCloneRef))
46430
46783
  return;
46431
46784
  const refsDir = luxttsCloneRefsDir();
46432
- if (!existsSync41(refsDir))
46785
+ if (!existsSync42(refsDir))
46433
46786
  return;
46434
46787
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
46435
- const p = join57(refsDir, name);
46436
- if (existsSync41(p)) {
46788
+ const p = join58(refsDir, name);
46789
+ if (existsSync42(p)) {
46437
46790
  this.luxttsCloneRef = p;
46438
46791
  return;
46439
46792
  }
@@ -46533,15 +46886,15 @@ if __name__ == '__main__':
46533
46886
  main()
46534
46887
  `;
46535
46888
  const scriptPath2 = luxttsInferScript();
46536
- mkdirSync17(voiceDir(), { recursive: true });
46537
- writeFileSync18(scriptPath2, script);
46889
+ mkdirSync18(voiceDir(), { recursive: true });
46890
+ writeFileSync19(scriptPath2, script);
46538
46891
  }
46539
46892
  /** Ensure the LuxTTS daemon is running, spawn if needed */
46540
46893
  async ensureLuxttsDaemon() {
46541
46894
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
46542
46895
  return true;
46543
46896
  const venvPy = luxttsVenvPy();
46544
- if (!existsSync41(venvPy))
46897
+ if (!existsSync42(venvPy))
46545
46898
  return false;
46546
46899
  return new Promise((resolve36) => {
46547
46900
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
@@ -46625,7 +46978,7 @@ if __name__ == '__main__':
46625
46978
  * Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
46626
46979
  */
46627
46980
  async synthesizeLuxttsWav(text, speedFactor = 1) {
46628
- if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
46981
+ if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
46629
46982
  return null;
46630
46983
  const cleaned = text.replace(/\*/g, "").trim();
46631
46984
  if (!cleaned)
@@ -46633,7 +46986,7 @@ if __name__ == '__main__':
46633
46986
  const ready = await this.ensureLuxttsDaemon();
46634
46987
  if (!ready)
46635
46988
  return null;
46636
- const wavPath = join57(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
46989
+ const wavPath = join58(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
46637
46990
  try {
46638
46991
  await this.luxttsRequest({
46639
46992
  action: "synthesize",
@@ -46645,17 +46998,17 @@ if __name__ == '__main__':
46645
46998
  } catch {
46646
46999
  return null;
46647
47000
  }
46648
- return existsSync41(wavPath) ? wavPath : null;
47001
+ return existsSync42(wavPath) ? wavPath : null;
46649
47002
  }
46650
47003
  /**
46651
47004
  * Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
46652
47005
  * Cleans up the WAV file after playback.
46653
47006
  */
46654
47007
  async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
46655
- if (!existsSync41(wavPath))
47008
+ if (!existsSync42(wavPath))
46656
47009
  return;
46657
47010
  try {
46658
- const wavData = readFileSync30(wavPath);
47011
+ const wavData = readFileSync31(wavPath);
46659
47012
  if (wavData.length > 44) {
46660
47013
  const sampleRate = wavData.readUInt32LE(24);
46661
47014
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -46670,13 +47023,13 @@ if __name__ == '__main__':
46670
47023
  }
46671
47024
  const header = wavData.subarray(0, 44);
46672
47025
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
46673
- writeFileSync18(wavPath, scaled);
47026
+ writeFileSync19(wavPath, scaled);
46674
47027
  }
46675
47028
  } catch {
46676
47029
  }
46677
47030
  if (pitchFactor !== 1) {
46678
47031
  try {
46679
- const wavData = readFileSync30(wavPath);
47032
+ const wavData = readFileSync31(wavPath);
46680
47033
  if (wavData.length > 44) {
46681
47034
  const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
46682
47035
  const float32 = new Float32Array(int16.length);
@@ -46691,7 +47044,7 @@ if __name__ == '__main__':
46691
47044
  }
46692
47045
  if (this.onPCMOutput) {
46693
47046
  try {
46694
- const wavData = readFileSync30(wavPath);
47047
+ const wavData = readFileSync31(wavPath);
46695
47048
  if (wavData.length > 44) {
46696
47049
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
46697
47050
  const sampleRate = wavData.readUInt32LE(24);
@@ -46702,7 +47055,7 @@ if __name__ == '__main__':
46702
47055
  }
46703
47056
  if (stereoDelayMs > 0) {
46704
47057
  try {
46705
- const wavData = readFileSync30(wavPath);
47058
+ const wavData = readFileSync31(wavPath);
46706
47059
  if (wavData.length > 44) {
46707
47060
  const sampleRate = wavData.readUInt32LE(24);
46708
47061
  const numChannels = wavData.readUInt16LE(22);
@@ -46738,7 +47091,7 @@ if __name__ == '__main__':
46738
47091
  * Used for Telegram voice messages and WebSocket streaming.
46739
47092
  */
46740
47093
  async synthesizeLuxttsToBuffer(text) {
46741
- if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
47094
+ if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
46742
47095
  return null;
46743
47096
  const cleaned = text.replace(/\*/g, "").trim();
46744
47097
  if (!cleaned)
@@ -46746,7 +47099,7 @@ if __name__ == '__main__':
46746
47099
  const ready = await this.ensureLuxttsDaemon();
46747
47100
  if (!ready)
46748
47101
  return null;
46749
- const wavPath = join57(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
47102
+ const wavPath = join58(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
46750
47103
  try {
46751
47104
  await this.luxttsRequest({
46752
47105
  action: "synthesize",
@@ -46758,10 +47111,10 @@ if __name__ == '__main__':
46758
47111
  } catch {
46759
47112
  return null;
46760
47113
  }
46761
- if (!existsSync41(wavPath))
47114
+ if (!existsSync42(wavPath))
46762
47115
  return null;
46763
47116
  try {
46764
- const data = readFileSync30(wavPath);
47117
+ const data = readFileSync31(wavPath);
46765
47118
  unlinkSync9(wavPath);
46766
47119
  return data;
46767
47120
  } catch {
@@ -46775,40 +47128,40 @@ if __name__ == '__main__':
46775
47128
  if (this.ort)
46776
47129
  return;
46777
47130
  const arch2 = process.arch;
46778
- mkdirSync17(voiceDir(), { recursive: true });
46779
- const pkgPath = join57(voiceDir(), "package.json");
47131
+ mkdirSync18(voiceDir(), { recursive: true });
47132
+ const pkgPath = join58(voiceDir(), "package.json");
46780
47133
  const expectedDeps = {
46781
47134
  "onnxruntime-node": "^1.21.0",
46782
47135
  "phonemizer": "^1.2.1"
46783
47136
  };
46784
- if (existsSync41(pkgPath)) {
47137
+ if (existsSync42(pkgPath)) {
46785
47138
  try {
46786
- const existing = JSON.parse(readFileSync30(pkgPath, "utf8"));
47139
+ const existing = JSON.parse(readFileSync31(pkgPath, "utf8"));
46787
47140
  if (!existing.dependencies?.["phonemizer"]) {
46788
47141
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
46789
- writeFileSync18(pkgPath, JSON.stringify(existing, null, 2));
47142
+ writeFileSync19(pkgPath, JSON.stringify(existing, null, 2));
46790
47143
  }
46791
47144
  } catch {
46792
47145
  }
46793
47146
  }
46794
- if (!existsSync41(pkgPath)) {
46795
- writeFileSync18(pkgPath, JSON.stringify({
47147
+ if (!existsSync42(pkgPath)) {
47148
+ writeFileSync19(pkgPath, JSON.stringify({
46796
47149
  name: "open-agents-voice",
46797
47150
  private: true,
46798
47151
  dependencies: expectedDeps
46799
47152
  }, null, 2));
46800
47153
  }
46801
- const voiceRequire = createRequire(join57(voiceDir(), "index.js"));
47154
+ const voiceRequire = createRequire(join58(voiceDir(), "index.js"));
46802
47155
  const probeOnnx = async () => {
46803
47156
  try {
46804
- 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);
47157
+ const output = await this.asyncShell(`NODE_PATH="${join58(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
46805
47158
  return output.trim() === "OK";
46806
47159
  } catch {
46807
47160
  return false;
46808
47161
  }
46809
47162
  };
46810
- const onnxNodeModules = join57(voiceDir(), "node_modules", "onnxruntime-node");
46811
- const onnxInstalled = existsSync41(onnxNodeModules);
47163
+ const onnxNodeModules = join58(voiceDir(), "node_modules", "onnxruntime-node");
47164
+ const onnxInstalled = existsSync42(onnxNodeModules);
46812
47165
  if (onnxInstalled && !await probeOnnx()) {
46813
47166
  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.`);
46814
47167
  }
@@ -46858,18 +47211,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46858
47211
  const dir = modelDir(id);
46859
47212
  const onnxPath = modelOnnxPath(id);
46860
47213
  const configPath2 = modelConfigPath(id);
46861
- if (existsSync41(onnxPath) && existsSync41(configPath2))
47214
+ if (existsSync42(onnxPath) && existsSync42(configPath2))
46862
47215
  return;
46863
- mkdirSync17(dir, { recursive: true });
46864
- if (!existsSync41(configPath2)) {
47216
+ mkdirSync18(dir, { recursive: true });
47217
+ if (!existsSync42(configPath2)) {
46865
47218
  renderInfo(`Downloading ${model.label} voice config...`);
46866
47219
  const configResp = await fetch(model.configUrl);
46867
47220
  if (!configResp.ok)
46868
47221
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
46869
47222
  const configText = await configResp.text();
46870
- writeFileSync18(configPath2, configText);
47223
+ writeFileSync19(configPath2, configText);
46871
47224
  }
46872
- if (!existsSync41(onnxPath)) {
47225
+ if (!existsSync42(onnxPath)) {
46873
47226
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
46874
47227
  const onnxResp = await fetch(model.onnxUrl);
46875
47228
  if (!onnxResp.ok)
@@ -46894,7 +47247,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46894
47247
  }
46895
47248
  }
46896
47249
  const fullBuffer = Buffer.concat(chunks);
46897
- writeFileSync18(onnxPath, fullBuffer);
47250
+ writeFileSync19(onnxPath, fullBuffer);
46898
47251
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
46899
47252
  }
46900
47253
  }
@@ -46906,10 +47259,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46906
47259
  throw new Error("ONNX runtime not loaded");
46907
47260
  const onnxPath = modelOnnxPath(this.modelId);
46908
47261
  const configPath2 = modelConfigPath(this.modelId);
46909
- if (!existsSync41(onnxPath) || !existsSync41(configPath2)) {
47262
+ if (!existsSync42(onnxPath) || !existsSync42(configPath2)) {
46910
47263
  throw new Error(`Model files not found for ${this.modelId}`);
46911
47264
  }
46912
- this.config = JSON.parse(readFileSync30(configPath2, "utf8"));
47265
+ this.config = JSON.parse(readFileSync31(configPath2, "utf8"));
46913
47266
  this.session = await this.ort.InferenceSession.create(onnxPath, {
46914
47267
  executionProviders: ["cpu"],
46915
47268
  graphOptimizationLevel: "all"
@@ -46936,8 +47289,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46936
47289
  // packages/cli/dist/tui/commands.js
46937
47290
  import * as nodeOs from "node:os";
46938
47291
  import { execSync as nodeExecSync } from "node:child_process";
46939
- import { existsSync as existsSync42, readFileSync as readFileSync31, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
46940
- import { join as join58 } from "node:path";
47292
+ import { existsSync as existsSync43, readFileSync as readFileSync32, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
47293
+ import { join as join59 } from "node:path";
46941
47294
  function safeLog(text) {
46942
47295
  if (isNeovimActive()) {
46943
47296
  writeToNeovimOutput(text + "\n");
@@ -47356,9 +47709,9 @@ async function handleSlashCommand(input, ctx) {
47356
47709
  renderInfo("No wallet configured. Ask the agent to create one via the nexus tool.");
47357
47710
  }
47358
47711
  } else if (sub === "name") {
47359
- const { homedir: homedir20 } = __require("node:os");
47712
+ const { homedir: homedir21 } = __require("node:os");
47360
47713
  const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
47361
- const namePath = __require("node:path").join(homedir20(), ".open-agents", "agent-name");
47714
+ const namePath = __require("node:path").join(homedir21(), ".open-agents", "agent-name");
47362
47715
  if (rest2) {
47363
47716
  const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
47364
47717
  if (!customName) {
@@ -47631,22 +47984,22 @@ async function handleSlashCommand(input, ctx) {
47631
47984
  let content = "";
47632
47985
  let metadata = {};
47633
47986
  if (shareType === "tool") {
47634
- const toolDir = join58(ctx.repoRoot, ".oa", "tools");
47635
- const toolFile = join58(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
47636
- if (!existsSync42(toolFile)) {
47987
+ const toolDir = join59(ctx.repoRoot, ".oa", "tools");
47988
+ const toolFile = join59(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
47989
+ if (!existsSync43(toolFile)) {
47637
47990
  renderWarning(`Tool not found: ${toolFile}`);
47638
47991
  return "handled";
47639
47992
  }
47640
- content = readFileSync31(toolFile, "utf8");
47993
+ content = readFileSync32(toolFile, "utf8");
47641
47994
  metadata = { type: "tool", name: shareName };
47642
47995
  } else if (shareType === "skill") {
47643
- const skillDir = join58(ctx.repoRoot, ".oa", "skills", shareName);
47644
- const skillFile = join58(skillDir, "SKILL.md");
47645
- if (!existsSync42(skillFile)) {
47996
+ const skillDir = join59(ctx.repoRoot, ".oa", "skills", shareName);
47997
+ const skillFile = join59(skillDir, "SKILL.md");
47998
+ if (!existsSync43(skillFile)) {
47646
47999
  renderWarning(`Skill not found: ${skillFile}`);
47647
48000
  return "handled";
47648
48001
  }
47649
- content = readFileSync31(skillFile, "utf8");
48002
+ content = readFileSync32(skillFile, "utf8");
47650
48003
  metadata = { type: "skill", name: shareName };
47651
48004
  } else {
47652
48005
  renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
@@ -47683,9 +48036,9 @@ async function handleSlashCommand(input, ctx) {
47683
48036
  try {
47684
48037
  const nexus = new NexusTool(ctx.repoRoot);
47685
48038
  await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
47686
- const regFile = join58(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
47687
- if (existsSync42(regFile)) {
47688
- const reg = JSON.parse(readFileSync31(regFile, "utf8"));
48039
+ const regFile = join59(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
48040
+ if (existsSync43(regFile)) {
48041
+ const reg = JSON.parse(readFileSync32(regFile, "utf8"));
47689
48042
  const pinned = Object.values(reg).some((e) => e.cid === importCid && e.pinned);
47690
48043
  if (pinned) {
47691
48044
  renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
@@ -47737,33 +48090,33 @@ async function handleSlashCommand(input, ctx) {
47737
48090
  lines.push(`
47738
48091
  ${c2.bold("IPFS / Helia Status")}
47739
48092
  `);
47740
- const ipfsDir = join58(ctx.repoRoot, ".oa", "ipfs");
47741
- const ipfsLocalDir = join58(ipfsDir, "local");
48093
+ const ipfsDir = join59(ctx.repoRoot, ".oa", "ipfs");
48094
+ const ipfsLocalDir = join59(ipfsDir, "local");
47742
48095
  let ipfsFiles = 0;
47743
48096
  let ipfsBytes = 0;
47744
48097
  let heliaBlocks = 0;
47745
48098
  let heliaBytes = 0;
47746
48099
  try {
47747
- if (existsSync42(ipfsLocalDir)) {
48100
+ if (existsSync43(ipfsLocalDir)) {
47748
48101
  const files = readdirSync12(ipfsLocalDir).filter((f) => f.endsWith(".json"));
47749
48102
  ipfsFiles = files.length;
47750
48103
  for (const f of files) {
47751
48104
  try {
47752
- ipfsBytes += statSync14(join58(ipfsLocalDir, f)).size;
48105
+ ipfsBytes += statSync14(join59(ipfsLocalDir, f)).size;
47753
48106
  } catch {
47754
48107
  }
47755
48108
  }
47756
48109
  }
47757
- const heliaBlockDir = join58(ipfsDir, "blocks");
47758
- if (existsSync42(heliaBlockDir)) {
48110
+ const heliaBlockDir = join59(ipfsDir, "blocks");
48111
+ if (existsSync43(heliaBlockDir)) {
47759
48112
  const walkDir = (dir) => {
47760
48113
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
47761
48114
  if (entry.isDirectory())
47762
- walkDir(join58(dir, entry.name));
48115
+ walkDir(join59(dir, entry.name));
47763
48116
  else {
47764
48117
  heliaBlocks++;
47765
48118
  try {
47766
- heliaBytes += statSync14(join58(dir, entry.name)).size;
48119
+ heliaBytes += statSync14(join59(dir, entry.name)).size;
47767
48120
  } catch {
47768
48121
  }
47769
48122
  }
@@ -47779,9 +48132,9 @@ async function handleSlashCommand(input, ctx) {
47779
48132
  lines.push(` Blocks: ${c2.bold(String(heliaBlocks))} Size: ${c2.bold(formatFileSize(heliaBytes))}`);
47780
48133
  lines.push(` Backend: ${heliaBlocks > 0 ? c2.green("helia-ipfs") : c2.yellow("sha256-local (Helia not initialized)")}`);
47781
48134
  try {
47782
- const statusFile = join58(ctx.repoRoot, ".oa", "nexus", "status.json");
47783
- if (existsSync42(statusFile)) {
47784
- const status = JSON.parse(readFileSync31(statusFile, "utf8"));
48135
+ const statusFile = join59(ctx.repoRoot, ".oa", "nexus", "status.json");
48136
+ if (existsSync43(statusFile)) {
48137
+ const status = JSON.parse(readFileSync32(statusFile, "utf8"));
47785
48138
  if (status.peerId) {
47786
48139
  lines.push(`
47787
48140
  ${c2.bold("Peer Info")}`);
@@ -47800,11 +48153,11 @@ async function handleSlashCommand(input, ctx) {
47800
48153
  ${c2.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
47801
48154
  lines.push(`
47802
48155
  ${c2.bold("Identity Kernel")}`);
47803
- const idDir = join58(ctx.repoRoot, ".oa", "identity");
48156
+ const idDir = join59(ctx.repoRoot, ".oa", "identity");
47804
48157
  try {
47805
- const stateFile = join58(idDir, "self-state.json");
47806
- if (existsSync42(stateFile)) {
47807
- const state = JSON.parse(readFileSync31(stateFile, "utf8"));
48158
+ const stateFile = join59(idDir, "self-state.json");
48159
+ if (existsSync43(stateFile)) {
48160
+ const state = JSON.parse(readFileSync32(stateFile, "utf8"));
47808
48161
  lines.push(` Version: ${c2.bold("v" + (state.version ?? "?"))} Sessions: ${c2.bold(String(state.session_count ?? 0))}`);
47809
48162
  if (state.narrative_summary) {
47810
48163
  lines.push(` Narrative: ${c2.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
@@ -47813,9 +48166,9 @@ async function handleSlashCommand(input, ctx) {
47813
48166
  const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
47814
48167
  lines.push(` Traits: ${c2.dim(traits.slice(0, 60))}`);
47815
48168
  }
47816
- const cidFile = join58(idDir, "cids.json");
47817
- if (existsSync42(cidFile)) {
47818
- const cids = JSON.parse(readFileSync31(cidFile, "utf8"));
48169
+ const cidFile = join59(idDir, "cids.json");
48170
+ if (existsSync43(cidFile)) {
48171
+ const cids = JSON.parse(readFileSync32(cidFile, "utf8"));
47819
48172
  const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
47820
48173
  if (lastCid)
47821
48174
  lines.push(` Last CID: ${c2.dim(String(lastCid).slice(0, 50))}`);
@@ -47828,9 +48181,9 @@ async function handleSlashCommand(input, ctx) {
47828
48181
  lines.push(`
47829
48182
  ${c2.bold("Memory Sentiment")}`);
47830
48183
  try {
47831
- const metaFile = join58(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
47832
- if (existsSync42(metaFile)) {
47833
- const store = JSON.parse(readFileSync31(metaFile, "utf8"));
48184
+ const metaFile = join59(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
48185
+ if (existsSync43(metaFile)) {
48186
+ const store = JSON.parse(readFileSync32(metaFile, "utf8"));
47834
48187
  const active = store.filter((m) => m.type !== "quarantine");
47835
48188
  const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
47836
48189
  const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
@@ -47848,8 +48201,8 @@ async function handleSlashCommand(input, ctx) {
47848
48201
  } catch {
47849
48202
  }
47850
48203
  try {
47851
- const dbPath = join58(ctx.repoRoot, ".oa", "memory", "structured.db");
47852
- if (existsSync42(dbPath)) {
48204
+ const dbPath = join59(ctx.repoRoot, ".oa", "memory", "structured.db");
48205
+ if (existsSync43(dbPath)) {
47853
48206
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
47854
48207
  const db = initDb2(dbPath);
47855
48208
  const memStore = new ProceduralMemoryStore2(db);
@@ -47870,8 +48223,8 @@ async function handleSlashCommand(input, ctx) {
47870
48223
  lines.push(`
47871
48224
  ${c2.bold("Storage Overview")}
47872
48225
  `);
47873
- const oaDir = join58(ctx.repoRoot, ".oa");
47874
- if (!existsSync42(oaDir)) {
48226
+ const oaDir = join59(ctx.repoRoot, ".oa");
48227
+ if (!existsSync43(oaDir)) {
47875
48228
  lines.push(` ${c2.dim("No .oa/ directory found.")}`);
47876
48229
  safeLog(lines.join("\n") + "\n");
47877
48230
  return "handled";
@@ -47881,7 +48234,7 @@ async function handleSlashCommand(input, ctx) {
47881
48234
  const walkStorage = (dir, category) => {
47882
48235
  try {
47883
48236
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
47884
- const full = join58(dir, entry.name);
48237
+ const full = join59(dir, entry.name);
47885
48238
  if (entry.isDirectory()) {
47886
48239
  const subCat = category || entry.name;
47887
48240
  walkStorage(full, subCat);
@@ -47917,10 +48270,10 @@ async function handleSlashCommand(input, ctx) {
47917
48270
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
47918
48271
  const name = entry.name.toLowerCase();
47919
48272
  if (sensitivePatterns.some((p) => name.includes(p))) {
47920
- sensitiveFound.push(join58(dir, entry.name).replace(oaDir + "/", ""));
48273
+ sensitiveFound.push(join59(dir, entry.name).replace(oaDir + "/", ""));
47921
48274
  }
47922
48275
  if (entry.isDirectory())
47923
- checkSensitive(join58(dir, entry.name));
48276
+ checkSensitive(join59(dir, entry.name));
47924
48277
  }
47925
48278
  } catch {
47926
48279
  }
@@ -47948,8 +48301,8 @@ async function handleSlashCommand(input, ctx) {
47948
48301
  renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
47949
48302
  return "handled";
47950
48303
  }
47951
- const resolvedPath = join58(ctx.repoRoot, filePath);
47952
- if (!existsSync42(resolvedPath)) {
48304
+ const resolvedPath = join59(ctx.repoRoot, filePath);
48305
+ if (!existsSync43(resolvedPath)) {
47953
48306
  renderWarning(`File not found: ${resolvedPath}`);
47954
48307
  return "handled";
47955
48308
  }
@@ -47965,9 +48318,9 @@ async function handleSlashCommand(input, ctx) {
47965
48318
  }
47966
48319
  try {
47967
48320
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
47968
- const dbDir = join58(ctx.repoRoot, ".oa", "memory");
47969
- mkdirSync18(dbDir, { recursive: true });
47970
- const db = initDb2(join58(dbDir, "structured.db"));
48321
+ const dbDir = join59(ctx.repoRoot, ".oa", "memory");
48322
+ mkdirSync19(dbDir, { recursive: true });
48323
+ const db = initDb2(join59(dbDir, "structured.db"));
47971
48324
  const memStore = new ProceduralMemoryStore2(db);
47972
48325
  if (isAudio) {
47973
48326
  renderInfo(`Transcribing: ${filePath}...`);
@@ -48008,7 +48361,7 @@ async function handleSlashCommand(input, ctx) {
48008
48361
  return "handled";
48009
48362
  }
48010
48363
  } else {
48011
- content = readFileSync31(resolvedPath, "utf8");
48364
+ content = readFileSync32(resolvedPath, "utf8");
48012
48365
  }
48013
48366
  if (!content.trim()) {
48014
48367
  renderWarning("No content extracted.");
@@ -48047,9 +48400,9 @@ async function handleSlashCommand(input, ctx) {
48047
48400
  }
48048
48401
  case "fortemi": {
48049
48402
  const fortemiSubCmd = (arg || "").trim().toLowerCase();
48050
- const fortemiDir = join58(ctx.repoRoot, "..", "fortemi-react");
48051
- const altFortemiDir = join58(nodeOs.homedir(), "fortemi-react");
48052
- const fDir = existsSync42(fortemiDir) ? fortemiDir : existsSync42(altFortemiDir) ? altFortemiDir : null;
48403
+ const fortemiDir = join59(ctx.repoRoot, "..", "fortemi-react");
48404
+ const altFortemiDir = join59(nodeOs.homedir(), "fortemi-react");
48405
+ const fDir = existsSync43(fortemiDir) ? fortemiDir : existsSync43(altFortemiDir) ? altFortemiDir : null;
48053
48406
  if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
48054
48407
  if (!fDir) {
48055
48408
  renderWarning("fortemi-react not found adjacent or in home directory.");
@@ -48064,14 +48417,14 @@ async function handleSlashCommand(input, ctx) {
48064
48417
  // 24h
48065
48418
  nonce: Math.random().toString(36).slice(2, 10)
48066
48419
  };
48067
- const jwtFile = join58(ctx.repoRoot, ".oa", "fortemi-jwt.json");
48068
- mkdirSync18(join58(ctx.repoRoot, ".oa"), { recursive: true });
48069
- writeFileSync19(jwtFile, JSON.stringify(jwtPayload, null, 2));
48420
+ const jwtFile = join59(ctx.repoRoot, ".oa", "fortemi-jwt.json");
48421
+ mkdirSync19(join59(ctx.repoRoot, ".oa"), { recursive: true });
48422
+ writeFileSync20(jwtFile, JSON.stringify(jwtPayload, null, 2));
48070
48423
  renderInfo(`Launching fortemi-react from ${fDir}...`);
48071
48424
  try {
48072
- const { spawn: spawn22 } = __require("node:child_process");
48073
- const child = spawn22("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
48074
- cwd: join58(fDir, "apps", "standalone"),
48425
+ const { spawn: spawn23 } = __require("node:child_process");
48426
+ const child = spawn23("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
48427
+ cwd: join59(fDir, "apps", "standalone"),
48075
48428
  stdio: "ignore",
48076
48429
  detached: true,
48077
48430
  env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
@@ -48080,8 +48433,8 @@ async function handleSlashCommand(input, ctx) {
48080
48433
  renderInfo("Fortemi-React starting on http://localhost:3000");
48081
48434
  renderInfo(`JWT saved to ${jwtFile}`);
48082
48435
  renderInfo("Memory operations will proxy to fortemi when available.");
48083
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48084
- writeFileSync19(bridgeFile, JSON.stringify({
48436
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48437
+ writeFileSync20(bridgeFile, JSON.stringify({
48085
48438
  url: "http://localhost:3000",
48086
48439
  pid: child.pid,
48087
48440
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -48093,12 +48446,12 @@ async function handleSlashCommand(input, ctx) {
48093
48446
  return "handled";
48094
48447
  }
48095
48448
  if (fortemiSubCmd === "status") {
48096
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48097
- if (!existsSync42(bridgeFile)) {
48449
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48450
+ if (!existsSync43(bridgeFile)) {
48098
48451
  renderInfo("Fortemi bridge: not connected. Run /fortemi start");
48099
48452
  return "handled";
48100
48453
  }
48101
- const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
48454
+ const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
48102
48455
  let alive = false;
48103
48456
  try {
48104
48457
  process.kill(bridge.pid, 0);
@@ -48118,15 +48471,15 @@ async function handleSlashCommand(input, ctx) {
48118
48471
  lines.push(` Process: ${alive ? c2.green("running") : c2.yellow("not running")} (PID ${bridge.pid})`);
48119
48472
  lines.push(` HTTP: ${httpOk ? c2.green("connected") : c2.yellow("unreachable")}`);
48120
48473
  lines.push(` Started: ${bridge.startedAt}`);
48121
- lines.push(` JWT: ${existsSync42(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
48474
+ lines.push(` JWT: ${existsSync43(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
48122
48475
  lines.push("");
48123
48476
  safeLog(lines.join("\n"));
48124
48477
  return "handled";
48125
48478
  }
48126
48479
  if (fortemiSubCmd === "stop") {
48127
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48128
- if (existsSync42(bridgeFile)) {
48129
- const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
48480
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48481
+ if (existsSync43(bridgeFile)) {
48482
+ const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
48130
48483
  try {
48131
48484
  process.kill(bridge.pid, "SIGTERM");
48132
48485
  } catch {
@@ -48183,6 +48536,37 @@ async function handleSlashCommand(input, ctx) {
48183
48536
  ctx.saveSettings(settings);
48184
48537
  };
48185
48538
  if (arg) {
48539
+ if (arg === "personaplex" || arg === "pp") {
48540
+ const { detectPersonaPlexCapability: detectPersonaPlexCapability2, isPersonaPlexInstalled: isPersonaPlexInstalled2, installPersonaPlex: installPersonaPlex2, startPersonaPlexDaemon: startPersonaPlexDaemon2, stopPersonaPlex: stopPersonaPlex2, isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
48541
+ const caps = detectPersonaPlexCapability2();
48542
+ if (!caps.supported) {
48543
+ renderWarning(`PersonaPlex not available: ${caps.reason}`);
48544
+ renderInfo("Requirements: NVIDIA GPU with \u226516GB VRAM (RTX 3090/4090/A100+), CUDA 12.1+, PyTorch");
48545
+ return "handled";
48546
+ }
48547
+ renderInfo(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB VRAM) \u2014 PersonaPlex compatible \u2713`);
48548
+ if (!isPersonaPlexInstalled2()) {
48549
+ renderInfo("Installing PersonaPlex-7B (~14GB download)...");
48550
+ const ok = await installPersonaPlex2((msg2) => renderInfo(msg2));
48551
+ if (!ok) {
48552
+ renderError("PersonaPlex installation failed.");
48553
+ return "handled";
48554
+ }
48555
+ }
48556
+ if (isPersonaPlexRunning2()) {
48557
+ renderInfo("PersonaPlex daemon is running.");
48558
+ renderInfo("Use /call to start a full-duplex voice session.");
48559
+ } else {
48560
+ const url = await startPersonaPlexDaemon2((msg2) => renderInfo(msg2));
48561
+ if (url) {
48562
+ renderInfo(`PersonaPlex ready at ${url}`);
48563
+ renderInfo("Use /call to start a full-duplex voice session with PersonaPlex.");
48564
+ } else {
48565
+ renderError("PersonaPlex daemon failed to start.");
48566
+ }
48567
+ }
48568
+ return "handled";
48569
+ }
48186
48570
  if (arg === "enable" || arg === "on") {
48187
48571
  const msg2 = await ctx.voiceToggle();
48188
48572
  const isOn = msg2.toLowerCase().includes("enabled") || msg2.toLowerCase().includes("on");
@@ -48474,6 +48858,17 @@ async function handleSlashCommand(input, ctx) {
48474
48858
  renderWarning("Call mode not available in this context.");
48475
48859
  return "handled";
48476
48860
  }
48861
+ try {
48862
+ const { isPersonaPlexRunning: isPersonaPlexRunning2, getPersonaPlexWSUrl: getPersonaPlexWSUrl2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
48863
+ if (isPersonaPlexRunning2()) {
48864
+ const ppUrl = getPersonaPlexWSUrl2();
48865
+ if (ppUrl) {
48866
+ renderInfo(`PersonaPlex active \u2014 full-duplex mode (${ppUrl})`);
48867
+ renderInfo("257ms response latency, concurrent listen+speak");
48868
+ }
48869
+ }
48870
+ } catch {
48871
+ }
48477
48872
  if (arg === "stop" || arg === "off") {
48478
48873
  if (ctx.isCallActive?.()) {
48479
48874
  await ctx.callStop?.();
@@ -48707,10 +49102,10 @@ async function handleSlashCommand(input, ctx) {
48707
49102
  let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
48708
49103
  if (!sponsorName || sponsorName.length < 2) {
48709
49104
  try {
48710
- const { homedir: homedir20 } = __require("os");
48711
- const namePath = __require("path").join(homedir20(), ".open-agents", "agent-name");
48712
- if (existsSync42(namePath))
48713
- sponsorName = readFileSync31(namePath, "utf8").trim();
49105
+ const { homedir: homedir21 } = __require("os");
49106
+ const namePath = __require("path").join(homedir21(), ".open-agents", "agent-name");
49107
+ if (existsSync43(namePath))
49108
+ sponsorName = readFileSync32(namePath, "utf8").trim();
48714
49109
  } catch {
48715
49110
  }
48716
49111
  if (!sponsorName)
@@ -49781,13 +50176,13 @@ async function showCohereDashboard(ctx) {
49781
50176
  } else if (idResult.key === "view") {
49782
50177
  await ik.execute({ operation: "hydrate" });
49783
50178
  } else if (idResult.key === "history") {
49784
- const snapDir = join58(ctx.repoRoot, ".oa", "identity", "snapshots");
49785
- if (existsSync42(snapDir)) {
50179
+ const snapDir = join59(ctx.repoRoot, ".oa", "identity", "snapshots");
50180
+ if (existsSync43(snapDir)) {
49786
50181
  const snaps = readdirSync12(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
49787
50182
  const snapItems = snaps.slice(0, 20).map((f) => ({
49788
50183
  key: f,
49789
50184
  label: f.replace(".json", ""),
49790
- detail: `${formatFileSize(statSync14(join58(snapDir, f)).size)}`
50185
+ detail: `${formatFileSize(statSync14(join59(snapDir, f)).size)}`
49791
50186
  }));
49792
50187
  if (snapItems.length > 0) {
49793
50188
  await tuiSelect({
@@ -50108,12 +50503,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
50108
50503
  continue;
50109
50504
  }
50110
50505
  const { basename: basename18, join: pathJoin } = await import("node:path");
50111
- const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync30, existsSync: exists } = await import("node:fs");
50112
- const { homedir: homedir20 } = await import("node:os");
50506
+ const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync31, existsSync: exists } = await import("node:fs");
50507
+ const { homedir: homedir21 } = await import("node:os");
50113
50508
  const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
50114
- const destDir = pathJoin(homedir20(), ".open-agents", "voice", "models", modelName);
50509
+ const destDir = pathJoin(homedir21(), ".open-agents", "voice", "models", modelName);
50115
50510
  if (!exists(destDir))
50116
- mkdirSync30(destDir, { recursive: true });
50511
+ mkdirSync31(destDir, { recursive: true });
50117
50512
  copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
50118
50513
  copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
50119
50514
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -50740,11 +51135,11 @@ async function handleSponsoredEndpoint(ctx, local) {
50740
51135
  }
50741
51136
  } catch {
50742
51137
  }
50743
- const sponsorDir2 = join58(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
50744
- const knownFile = join58(sponsorDir2, "known-sponsors.json");
51138
+ const sponsorDir2 = join59(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
51139
+ const knownFile = join59(sponsorDir2, "known-sponsors.json");
50745
51140
  try {
50746
- if (existsSync42(knownFile)) {
50747
- const saved = JSON.parse(readFileSync31(knownFile, "utf8"));
51141
+ if (existsSync43(knownFile)) {
51142
+ const saved = JSON.parse(readFileSync32(knownFile, "utf8"));
50748
51143
  for (const s of saved) {
50749
51144
  if (!sponsors.some((sp) => sp.url === s.url)) {
50750
51145
  sponsors.push({ ...s, source: "saved" });
@@ -50879,11 +51274,11 @@ async function handleSponsoredEndpoint(ctx, local) {
50879
51274
  }
50880
51275
  const saveKey = selected.url || selected.peerId || selected.name;
50881
51276
  try {
50882
- mkdirSync18(sponsorDir2, { recursive: true });
50883
- const existing = existsSync42(knownFile) ? JSON.parse(readFileSync31(knownFile, "utf8")) : [];
51277
+ mkdirSync19(sponsorDir2, { recursive: true });
51278
+ const existing = existsSync43(knownFile) ? JSON.parse(readFileSync32(knownFile, "utf8")) : [];
50884
51279
  const updated = existing.filter((s) => (s.url || s.peerId || s.name) !== saveKey);
50885
51280
  updated.push(selected);
50886
- writeFileSync19(knownFile, JSON.stringify(updated, null, 2), "utf8");
51281
+ writeFileSync20(knownFile, JSON.stringify(updated, null, 2), "utf8");
50887
51282
  } catch {
50888
51283
  }
50889
51284
  renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
@@ -50952,11 +51347,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
50952
51347
  const models = await fetchModels(peerUrl, authKey);
50953
51348
  if (models.length > 0) {
50954
51349
  try {
50955
- const { writeFileSync: writeFileSync29, mkdirSync: mkdirSync30 } = await import("node:fs");
50956
- const { join: join76, dirname: dirname23 } = await import("node:path");
50957
- const cachePath = join76(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
50958
- mkdirSync30(dirname23(cachePath), { recursive: true });
50959
- writeFileSync29(cachePath, JSON.stringify({
51350
+ const { writeFileSync: writeFileSync30, mkdirSync: mkdirSync31 } = await import("node:fs");
51351
+ const { join: join77, dirname: dirname23 } = await import("node:path");
51352
+ const cachePath = join77(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
51353
+ mkdirSync31(dirname23(cachePath), { recursive: true });
51354
+ writeFileSync30(cachePath, JSON.stringify({
50960
51355
  peerId,
50961
51356
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
50962
51357
  models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
@@ -51005,7 +51400,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
51005
51400
  }
51006
51401
  }
51007
51402
  async function handleParallel(arg, ctx) {
51008
- const { execSync: execSync34 } = await import("node:child_process");
51403
+ const { execSync: execSync35 } = await import("node:child_process");
51009
51404
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
51010
51405
  const isRemote = ctx.config.backendType === "nexus";
51011
51406
  if (isRemote) {
@@ -51029,7 +51424,7 @@ async function handleParallel(arg, ctx) {
51029
51424
  }
51030
51425
  let systemdVal = "";
51031
51426
  try {
51032
- const out = execSync34("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
51427
+ const out = execSync35("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
51033
51428
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
51034
51429
  if (match)
51035
51430
  systemdVal = match[1];
@@ -51058,7 +51453,7 @@ async function handleParallel(arg, ctx) {
51058
51453
  }
51059
51454
  const isSystemd = (() => {
51060
51455
  try {
51061
- const out = execSync34("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
51456
+ const out = execSync35("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
51062
51457
  return out === "active" || out === "inactive";
51063
51458
  } catch {
51064
51459
  return false;
@@ -51072,10 +51467,10 @@ async function handleParallel(arg, ctx) {
51072
51467
  const overrideContent = `[Service]
51073
51468
  Environment="OLLAMA_NUM_PARALLEL=${n}"
51074
51469
  `;
51075
- execSync34(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
51076
- execSync34(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
51077
- execSync34("sudo systemctl daemon-reload", { stdio: "pipe" });
51078
- execSync34("sudo systemctl restart ollama.service", { stdio: "pipe" });
51470
+ execSync35(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
51471
+ execSync35(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
51472
+ execSync35("sudo systemctl daemon-reload", { stdio: "pipe" });
51473
+ execSync35("sudo systemctl restart ollama.service", { stdio: "pipe" });
51079
51474
  let ready = false;
51080
51475
  for (let i = 0; i < 30 && !ready; i++) {
51081
51476
  await new Promise((r) => setTimeout(r, 500));
@@ -51102,13 +51497,13 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
51102
51497
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
51103
51498
  try {
51104
51499
  try {
51105
- execSync34("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
51500
+ execSync35("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
51106
51501
  } catch {
51107
51502
  }
51108
51503
  await new Promise((r) => setTimeout(r, 1e3));
51109
51504
  process.env.OLLAMA_NUM_PARALLEL = String(n);
51110
- const { spawn: spawn22 } = await import("node:child_process");
51111
- const child = spawn22("ollama", ["serve"], {
51505
+ const { spawn: spawn23 } = await import("node:child_process");
51506
+ const child = spawn23("ollama", ["serve"], {
51112
51507
  stdio: "ignore",
51113
51508
  detached: true,
51114
51509
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
@@ -51155,17 +51550,17 @@ async function handleUpdate(subcommand, ctx) {
51155
51550
  try {
51156
51551
  const { createRequire: createRequire6 } = await import("node:module");
51157
51552
  const { fileURLToPath: fileURLToPath15 } = await import("node:url");
51158
- const { dirname: dirname23, join: join76 } = await import("node:path");
51159
- const { existsSync: existsSync56 } = await import("node:fs");
51553
+ const { dirname: dirname23, join: join77 } = await import("node:path");
51554
+ const { existsSync: existsSync57 } = await import("node:fs");
51160
51555
  const req = createRequire6(import.meta.url);
51161
51556
  const thisDir = dirname23(fileURLToPath15(import.meta.url));
51162
51557
  const candidates = [
51163
- join76(thisDir, "..", "package.json"),
51164
- join76(thisDir, "..", "..", "package.json"),
51165
- join76(thisDir, "..", "..", "..", "package.json")
51558
+ join77(thisDir, "..", "package.json"),
51559
+ join77(thisDir, "..", "..", "package.json"),
51560
+ join77(thisDir, "..", "..", "..", "package.json")
51166
51561
  ];
51167
51562
  for (const pkgPath of candidates) {
51168
- if (existsSync56(pkgPath)) {
51563
+ if (existsSync57(pkgPath)) {
51169
51564
  const pkg = req(pkgPath);
51170
51565
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
51171
51566
  currentVersion = pkg.version ?? "0.0.0";
@@ -51921,18 +52316,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
51921
52316
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
51922
52317
  let copied = false;
51923
52318
  try {
51924
- const { execSync: execSync34 } = __require("node:child_process");
52319
+ const { execSync: execSync35 } = __require("node:child_process");
51925
52320
  const platform6 = process.platform;
51926
52321
  if (platform6 === "darwin") {
51927
- execSync34("pbcopy", { input: cmd, timeout: 3e3 });
52322
+ execSync35("pbcopy", { input: cmd, timeout: 3e3 });
51928
52323
  copied = true;
51929
52324
  } else if (platform6 === "win32") {
51930
- execSync34("clip", { input: cmd, timeout: 3e3 });
52325
+ execSync35("clip", { input: cmd, timeout: 3e3 });
51931
52326
  copied = true;
51932
52327
  } else {
51933
52328
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
51934
52329
  try {
51935
- execSync34(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
52330
+ execSync35(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
51936
52331
  copied = true;
51937
52332
  break;
51938
52333
  } catch {
@@ -52019,10 +52414,10 @@ var init_commands = __esm({
52019
52414
  });
52020
52415
 
52021
52416
  // packages/cli/dist/tui/project-context.js
52022
- import { existsSync as existsSync43, readFileSync as readFileSync32, readdirSync as readdirSync13 } from "node:fs";
52023
- import { join as join59, basename as basename12 } from "node:path";
52024
- import { execSync as execSync30 } from "node:child_process";
52025
- import { homedir as homedir16, platform as platform4, release } from "node:os";
52417
+ import { existsSync as existsSync44, readFileSync as readFileSync33, readdirSync as readdirSync13 } from "node:fs";
52418
+ import { join as join60, basename as basename12 } from "node:path";
52419
+ import { execSync as execSync31 } from "node:child_process";
52420
+ import { homedir as homedir17, platform as platform4, release } from "node:os";
52026
52421
  function getModelTier(modelName) {
52027
52422
  const m = modelName.toLowerCase();
52028
52423
  const sizeMatch = m.match(/\b(\d+)b\b/);
@@ -52055,10 +52450,10 @@ function loadProjectMap(repoRoot) {
52055
52450
  if (!hasOaDirectory(repoRoot)) {
52056
52451
  initOaDirectory(repoRoot);
52057
52452
  }
52058
- const mapPath2 = join59(repoRoot, OA_DIR, "context", "project-map.md");
52059
- if (existsSync43(mapPath2)) {
52453
+ const mapPath2 = join60(repoRoot, OA_DIR, "context", "project-map.md");
52454
+ if (existsSync44(mapPath2)) {
52060
52455
  try {
52061
- const content = readFileSync32(mapPath2, "utf-8");
52456
+ const content = readFileSync33(mapPath2, "utf-8");
52062
52457
  return content;
52063
52458
  } catch {
52064
52459
  }
@@ -52067,19 +52462,19 @@ function loadProjectMap(repoRoot) {
52067
52462
  }
52068
52463
  function getGitInfo(repoRoot) {
52069
52464
  try {
52070
- execSync30("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
52465
+ execSync31("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
52071
52466
  } catch {
52072
52467
  return "";
52073
52468
  }
52074
52469
  const lines = [];
52075
52470
  try {
52076
- const branch = execSync30("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52471
+ const branch = execSync31("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52077
52472
  if (branch)
52078
52473
  lines.push(`Branch: ${branch}`);
52079
52474
  } catch {
52080
52475
  }
52081
52476
  try {
52082
- const status = execSync30("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52477
+ const status = execSync31("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52083
52478
  if (status) {
52084
52479
  const changed = status.split("\n").length;
52085
52480
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -52089,7 +52484,7 @@ function getGitInfo(repoRoot) {
52089
52484
  } catch {
52090
52485
  }
52091
52486
  try {
52092
- const log = execSync30("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52487
+ const log = execSync31("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52093
52488
  if (log)
52094
52489
  lines.push(`Recent commits:
52095
52490
  ${log}`);
@@ -52099,31 +52494,31 @@ ${log}`);
52099
52494
  }
52100
52495
  function loadMemoryContext(repoRoot) {
52101
52496
  const sections = [];
52102
- const oaMemDir = join59(repoRoot, OA_DIR, "memory");
52497
+ const oaMemDir = join60(repoRoot, OA_DIR, "memory");
52103
52498
  const oaEntries = loadMemoryDir(oaMemDir, "project");
52104
52499
  if (oaEntries)
52105
52500
  sections.push(oaEntries);
52106
- const legacyMemDir = join59(repoRoot, ".open-agents", "memory");
52107
- if (legacyMemDir !== oaMemDir && existsSync43(legacyMemDir)) {
52501
+ const legacyMemDir = join60(repoRoot, ".open-agents", "memory");
52502
+ if (legacyMemDir !== oaMemDir && existsSync44(legacyMemDir)) {
52108
52503
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
52109
52504
  if (legacyEntries)
52110
52505
  sections.push(legacyEntries);
52111
52506
  }
52112
- const globalMemDir = join59(homedir16(), ".open-agents", "memory");
52507
+ const globalMemDir = join60(homedir17(), ".open-agents", "memory");
52113
52508
  const globalEntries = loadMemoryDir(globalMemDir, "global");
52114
52509
  if (globalEntries)
52115
52510
  sections.push(globalEntries);
52116
52511
  return sections.join("\n\n");
52117
52512
  }
52118
52513
  function loadMemoryDir(memDir, scope) {
52119
- if (!existsSync43(memDir))
52514
+ if (!existsSync44(memDir))
52120
52515
  return "";
52121
52516
  const lines = [];
52122
52517
  try {
52123
52518
  const files = readdirSync13(memDir).filter((f) => f.endsWith(".json"));
52124
52519
  for (const file of files.slice(0, 10)) {
52125
52520
  try {
52126
- const raw = readFileSync32(join59(memDir, file), "utf-8");
52521
+ const raw = readFileSync33(join60(memDir, file), "utf-8");
52127
52522
  const entries = JSON.parse(raw);
52128
52523
  const topic = basename12(file, ".json");
52129
52524
  const keys = Object.keys(entries);
@@ -53263,8 +53658,8 @@ __export(banner_exports, {
53263
53658
  saveBannerDesign: () => saveBannerDesign,
53264
53659
  setGridText: () => setGridText
53265
53660
  });
53266
- import { existsSync as existsSync44, readFileSync as readFileSync33, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19 } from "node:fs";
53267
- import { join as join60 } from "node:path";
53661
+ import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20 } from "node:fs";
53662
+ import { join as join61 } from "node:path";
53268
53663
  function generateMnemonic(seed) {
53269
53664
  let h = 2166136261;
53270
53665
  for (let i = 0; i < seed.length; i++) {
@@ -53459,23 +53854,23 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
53459
53854
  };
53460
53855
  }
53461
53856
  function saveBannerDesign(workDir, design) {
53462
- const dir = join60(workDir, ".oa", "banners");
53463
- mkdirSync19(dir, { recursive: true });
53464
- writeFileSync20(join60(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
53857
+ const dir = join61(workDir, ".oa", "banners");
53858
+ mkdirSync20(dir, { recursive: true });
53859
+ writeFileSync21(join61(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
53465
53860
  }
53466
53861
  function loadBannerDesign(workDir, id) {
53467
- const file = join60(workDir, ".oa", "banners", `${id}.json`);
53468
- if (!existsSync44(file))
53862
+ const file = join61(workDir, ".oa", "banners", `${id}.json`);
53863
+ if (!existsSync45(file))
53469
53864
  return null;
53470
53865
  try {
53471
- return JSON.parse(readFileSync33(file, "utf8"));
53866
+ return JSON.parse(readFileSync34(file, "utf8"));
53472
53867
  } catch {
53473
53868
  return null;
53474
53869
  }
53475
53870
  }
53476
53871
  function listBannerDesigns(workDir) {
53477
- const dir = join60(workDir, ".oa", "banners");
53478
- if (!existsSync44(dir))
53872
+ const dir = join61(workDir, ".oa", "banners");
53873
+ if (!existsSync45(dir))
53479
53874
  return [];
53480
53875
  try {
53481
53876
  const { readdirSync: readdirSync23 } = __require("node:fs");
@@ -53833,22 +54228,22 @@ var init_banner = __esm({
53833
54228
  });
53834
54229
 
53835
54230
  // packages/cli/dist/tui/carousel-descriptors.js
53836
- import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20, readdirSync as readdirSync14 } from "node:fs";
53837
- import { join as join61, basename as basename13 } from "node:path";
54231
+ import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync22, mkdirSync as mkdirSync21, readdirSync as readdirSync14 } from "node:fs";
54232
+ import { join as join62, basename as basename13 } from "node:path";
53838
54233
  function loadToolProfile(repoRoot) {
53839
- const filePath = join61(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
54234
+ const filePath = join62(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
53840
54235
  try {
53841
- if (!existsSync45(filePath))
54236
+ if (!existsSync46(filePath))
53842
54237
  return null;
53843
- return JSON.parse(readFileSync34(filePath, "utf-8"));
54238
+ return JSON.parse(readFileSync35(filePath, "utf-8"));
53844
54239
  } catch {
53845
54240
  return null;
53846
54241
  }
53847
54242
  }
53848
54243
  function saveToolProfile(repoRoot, profile) {
53849
- const contextDir = join61(repoRoot, OA_DIR, "context");
53850
- mkdirSync20(contextDir, { recursive: true });
53851
- writeFileSync21(join61(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
54244
+ const contextDir = join62(repoRoot, OA_DIR, "context");
54245
+ mkdirSync21(contextDir, { recursive: true });
54246
+ writeFileSync22(join62(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
53852
54247
  }
53853
54248
  function categorizeToolCall(toolName) {
53854
54249
  for (const cat of TOOL_CATEGORIES) {
@@ -53906,25 +54301,25 @@ function weightedColor(profile) {
53906
54301
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
53907
54302
  }
53908
54303
  function loadCachedDescriptors(repoRoot) {
53909
- const filePath = join61(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
54304
+ const filePath = join62(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
53910
54305
  try {
53911
- if (!existsSync45(filePath))
54306
+ if (!existsSync46(filePath))
53912
54307
  return null;
53913
- const cached = JSON.parse(readFileSync34(filePath, "utf-8"));
54308
+ const cached = JSON.parse(readFileSync35(filePath, "utf-8"));
53914
54309
  return cached.phrases.length > 0 ? cached.phrases : null;
53915
54310
  } catch {
53916
54311
  return null;
53917
54312
  }
53918
54313
  }
53919
54314
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
53920
- const contextDir = join61(repoRoot, OA_DIR, "context");
53921
- mkdirSync20(contextDir, { recursive: true });
54315
+ const contextDir = join62(repoRoot, OA_DIR, "context");
54316
+ mkdirSync21(contextDir, { recursive: true });
53922
54317
  const cached = {
53923
54318
  phrases,
53924
54319
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
53925
54320
  sourceHash
53926
54321
  };
53927
- writeFileSync21(join61(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
54322
+ writeFileSync22(join62(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
53928
54323
  }
53929
54324
  function generateDescriptors(repoRoot) {
53930
54325
  const profile = loadToolProfile(repoRoot);
@@ -53972,11 +54367,11 @@ function generateDescriptors(repoRoot) {
53972
54367
  return phrases;
53973
54368
  }
53974
54369
  function extractFromPackageJson(repoRoot, tags) {
53975
- const pkgPath = join61(repoRoot, "package.json");
54370
+ const pkgPath = join62(repoRoot, "package.json");
53976
54371
  try {
53977
- if (!existsSync45(pkgPath))
54372
+ if (!existsSync46(pkgPath))
53978
54373
  return;
53979
- const pkg = JSON.parse(readFileSync34(pkgPath, "utf-8"));
54374
+ const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
53980
54375
  if (pkg.name && typeof pkg.name === "string") {
53981
54376
  const parts = pkg.name.replace(/^@/, "").split("/");
53982
54377
  for (const p of parts)
@@ -54020,7 +54415,7 @@ function extractFromManifests(repoRoot, tags) {
54020
54415
  { file: ".github/workflows", tag: "ci/cd" }
54021
54416
  ];
54022
54417
  for (const check of manifestChecks) {
54023
- if (existsSync45(join61(repoRoot, check.file))) {
54418
+ if (existsSync46(join62(repoRoot, check.file))) {
54024
54419
  tags.push(check.tag);
54025
54420
  }
54026
54421
  }
@@ -54042,16 +54437,16 @@ function extractFromSessions(repoRoot, tags) {
54042
54437
  }
54043
54438
  }
54044
54439
  function extractFromMemory(repoRoot, tags) {
54045
- const memoryDir = join61(repoRoot, OA_DIR, "memory");
54440
+ const memoryDir = join62(repoRoot, OA_DIR, "memory");
54046
54441
  try {
54047
- if (!existsSync45(memoryDir))
54442
+ if (!existsSync46(memoryDir))
54048
54443
  return;
54049
54444
  const files = readdirSync14(memoryDir).filter((f) => f.endsWith(".json"));
54050
54445
  for (const file of files) {
54051
54446
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
54052
54447
  tags.push(topic);
54053
54448
  try {
54054
- const data = JSON.parse(readFileSync34(join61(memoryDir, file), "utf-8"));
54449
+ const data = JSON.parse(readFileSync35(join62(memoryDir, file), "utf-8"));
54055
54450
  if (data && typeof data === "object") {
54056
54451
  const keys = Object.keys(data).slice(0, 3);
54057
54452
  for (const key of keys) {
@@ -54722,13 +55117,13 @@ var init_stream_renderer = __esm({
54722
55117
  });
54723
55118
 
54724
55119
  // packages/cli/dist/tui/edit-history.js
54725
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync21 } from "node:fs";
54726
- import { join as join62 } from "node:path";
55120
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync22 } from "node:fs";
55121
+ import { join as join63 } from "node:path";
54727
55122
  function createEditHistoryLogger(repoRoot, sessionId) {
54728
- const historyDir = join62(repoRoot, ".oa", "history");
54729
- const logPath2 = join62(historyDir, "edits.jsonl");
55123
+ const historyDir = join63(repoRoot, ".oa", "history");
55124
+ const logPath2 = join63(historyDir, "edits.jsonl");
54730
55125
  try {
54731
- mkdirSync21(historyDir, { recursive: true });
55126
+ mkdirSync22(historyDir, { recursive: true });
54732
55127
  } catch {
54733
55128
  }
54734
55129
  function logToolCall(toolName, toolArgs, success) {
@@ -54837,17 +55232,17 @@ var init_edit_history = __esm({
54837
55232
  });
54838
55233
 
54839
55234
  // packages/cli/dist/tui/promptLoader.js
54840
- import { readFileSync as readFileSync35, existsSync as existsSync46 } from "node:fs";
54841
- import { join as join63, dirname as dirname19 } from "node:path";
55235
+ import { readFileSync as readFileSync36, existsSync as existsSync47 } from "node:fs";
55236
+ import { join as join64, dirname as dirname19 } from "node:path";
54842
55237
  import { fileURLToPath as fileURLToPath11 } from "node:url";
54843
55238
  function loadPrompt3(promptPath, vars) {
54844
55239
  let content = cache3.get(promptPath);
54845
55240
  if (content === void 0) {
54846
- const fullPath = join63(PROMPTS_DIR3, promptPath);
54847
- if (!existsSync46(fullPath)) {
55241
+ const fullPath = join64(PROMPTS_DIR3, promptPath);
55242
+ if (!existsSync47(fullPath)) {
54848
55243
  throw new Error(`Prompt file not found: ${fullPath}`);
54849
55244
  }
54850
- content = readFileSync35(fullPath, "utf-8");
55245
+ content = readFileSync36(fullPath, "utf-8");
54851
55246
  cache3.set(promptPath, content);
54852
55247
  }
54853
55248
  if (!vars)
@@ -54860,23 +55255,23 @@ var init_promptLoader3 = __esm({
54860
55255
  "use strict";
54861
55256
  __filename3 = fileURLToPath11(import.meta.url);
54862
55257
  __dirname6 = dirname19(__filename3);
54863
- devPath2 = join63(__dirname6, "..", "..", "prompts");
54864
- publishedPath2 = join63(__dirname6, "..", "prompts");
54865
- PROMPTS_DIR3 = existsSync46(devPath2) ? devPath2 : publishedPath2;
55258
+ devPath2 = join64(__dirname6, "..", "..", "prompts");
55259
+ publishedPath2 = join64(__dirname6, "..", "prompts");
55260
+ PROMPTS_DIR3 = existsSync47(devPath2) ? devPath2 : publishedPath2;
54866
55261
  cache3 = /* @__PURE__ */ new Map();
54867
55262
  }
54868
55263
  });
54869
55264
 
54870
55265
  // packages/cli/dist/tui/dream-engine.js
54871
- import { mkdirSync as mkdirSync22, writeFileSync as writeFileSync22, readFileSync as readFileSync36, existsSync as existsSync47, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
54872
- import { join as join64, basename as basename14 } from "node:path";
54873
- import { execSync as execSync31 } from "node:child_process";
55266
+ import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync23, readFileSync as readFileSync37, existsSync as existsSync48, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
55267
+ import { join as join65, basename as basename14 } from "node:path";
55268
+ import { execSync as execSync32 } from "node:child_process";
54874
55269
  function loadAutoresearchMemory(repoRoot) {
54875
- const memoryPath = join64(repoRoot, ".oa", "memory", "autoresearch.json");
54876
- if (!existsSync47(memoryPath))
55270
+ const memoryPath = join65(repoRoot, ".oa", "memory", "autoresearch.json");
55271
+ if (!existsSync48(memoryPath))
54877
55272
  return "";
54878
55273
  try {
54879
- const raw = readFileSync36(memoryPath, "utf-8");
55274
+ const raw = readFileSync37(memoryPath, "utf-8");
54880
55275
  const data = JSON.parse(raw);
54881
55276
  const sections = [];
54882
55277
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -55066,14 +55461,14 @@ var init_dream_engine = __esm({
55066
55461
  const content = String(args["content"] ?? "");
55067
55462
  if (!rawPath)
55068
55463
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
55069
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join64(this.autoresearchDir, basename14(rawPath)) : join64(this.autoresearchDir, rawPath);
55464
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
55070
55465
  if (!targetPath.startsWith(this.autoresearchDir)) {
55071
55466
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
55072
55467
  }
55073
55468
  try {
55074
- const dir = join64(targetPath, "..");
55075
- mkdirSync22(dir, { recursive: true });
55076
- writeFileSync22(targetPath, content, "utf-8");
55469
+ const dir = join65(targetPath, "..");
55470
+ mkdirSync23(dir, { recursive: true });
55471
+ writeFileSync23(targetPath, content, "utf-8");
55077
55472
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
55078
55473
  } catch (err) {
55079
55474
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55101,20 +55496,20 @@ var init_dream_engine = __esm({
55101
55496
  const rawPath = String(args["path"] ?? "");
55102
55497
  const oldStr = String(args["old_string"] ?? "");
55103
55498
  const newStr = String(args["new_string"] ?? "");
55104
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join64(this.autoresearchDir, basename14(rawPath)) : join64(this.autoresearchDir, rawPath);
55499
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
55105
55500
  if (!targetPath.startsWith(this.autoresearchDir)) {
55106
55501
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
55107
55502
  }
55108
55503
  try {
55109
- if (!existsSync47(targetPath)) {
55504
+ if (!existsSync48(targetPath)) {
55110
55505
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
55111
55506
  }
55112
- let content = readFileSync36(targetPath, "utf-8");
55507
+ let content = readFileSync37(targetPath, "utf-8");
55113
55508
  if (!content.includes(oldStr)) {
55114
55509
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
55115
55510
  }
55116
55511
  content = content.replace(oldStr, newStr);
55117
- writeFileSync22(targetPath, content, "utf-8");
55512
+ writeFileSync23(targetPath, content, "utf-8");
55118
55513
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
55119
55514
  } catch (err) {
55120
55515
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55155,14 +55550,14 @@ var init_dream_engine = __esm({
55155
55550
  const content = String(args["content"] ?? "");
55156
55551
  if (!rawPath)
55157
55552
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
55158
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join64(this.dreamsDir, basename14(rawPath)) : join64(this.dreamsDir, rawPath);
55553
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
55159
55554
  if (!targetPath.startsWith(this.dreamsDir)) {
55160
55555
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
55161
55556
  }
55162
55557
  try {
55163
- const dir = join64(targetPath, "..");
55164
- mkdirSync22(dir, { recursive: true });
55165
- writeFileSync22(targetPath, content, "utf-8");
55558
+ const dir = join65(targetPath, "..");
55559
+ mkdirSync23(dir, { recursive: true });
55560
+ writeFileSync23(targetPath, content, "utf-8");
55166
55561
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
55167
55562
  } catch (err) {
55168
55563
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55190,20 +55585,20 @@ var init_dream_engine = __esm({
55190
55585
  const rawPath = String(args["path"] ?? "");
55191
55586
  const oldStr = String(args["old_string"] ?? "");
55192
55587
  const newStr = String(args["new_string"] ?? "");
55193
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join64(this.dreamsDir, basename14(rawPath)) : join64(this.dreamsDir, rawPath);
55588
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
55194
55589
  if (!targetPath.startsWith(this.dreamsDir)) {
55195
55590
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
55196
55591
  }
55197
55592
  try {
55198
- if (!existsSync47(targetPath)) {
55593
+ if (!existsSync48(targetPath)) {
55199
55594
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
55200
55595
  }
55201
- let content = readFileSync36(targetPath, "utf-8");
55596
+ let content = readFileSync37(targetPath, "utf-8");
55202
55597
  if (!content.includes(oldStr)) {
55203
55598
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
55204
55599
  }
55205
55600
  content = content.replace(oldStr, newStr);
55206
- writeFileSync22(targetPath, content, "utf-8");
55601
+ writeFileSync23(targetPath, content, "utf-8");
55207
55602
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
55208
55603
  } catch (err) {
55209
55604
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55234,7 +55629,7 @@ var init_dream_engine = __esm({
55234
55629
  }
55235
55630
  }
55236
55631
  try {
55237
- const output = execSync31(cmd, {
55632
+ const output = execSync32(cmd, {
55238
55633
  cwd: this.repoRoot,
55239
55634
  timeout: 3e4,
55240
55635
  encoding: "utf-8",
@@ -55257,7 +55652,7 @@ var init_dream_engine = __esm({
55257
55652
  constructor(config, repoRoot) {
55258
55653
  this.config = config;
55259
55654
  this.repoRoot = repoRoot;
55260
- this.dreamsDir = join64(repoRoot, ".oa", "dreams");
55655
+ this.dreamsDir = join65(repoRoot, ".oa", "dreams");
55261
55656
  this.state = {
55262
55657
  mode: "default",
55263
55658
  active: false,
@@ -55288,7 +55683,7 @@ var init_dream_engine = __esm({
55288
55683
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
55289
55684
  results: []
55290
55685
  };
55291
- mkdirSync22(this.dreamsDir, { recursive: true });
55686
+ mkdirSync23(this.dreamsDir, { recursive: true });
55292
55687
  this.saveDreamState();
55293
55688
  try {
55294
55689
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -55341,8 +55736,8 @@ ${result.summary}`;
55341
55736
  if (mode !== "default" || cycle === totalCycles) {
55342
55737
  renderDreamContraction(cycle);
55343
55738
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
55344
- const summaryPath = join64(this.dreamsDir, `cycle-${cycle}-summary.md`);
55345
- writeFileSync22(summaryPath, cycleSummary, "utf-8");
55739
+ const summaryPath = join65(this.dreamsDir, `cycle-${cycle}-summary.md`);
55740
+ writeFileSync23(summaryPath, cycleSummary, "utf-8");
55346
55741
  }
55347
55742
  if (mode === "lucid" && !this.abortController.signal.aborted) {
55348
55743
  this.saveVersionCheckpoint(cycle);
@@ -55554,7 +55949,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
55554
55949
  }
55555
55950
  /** Build role-specific tool sets for swarm agents */
55556
55951
  buildSwarmTools(role, _workspace) {
55557
- const autoresearchDir = join64(this.repoRoot, ".oa", "autoresearch");
55952
+ const autoresearchDir = join65(this.repoRoot, ".oa", "autoresearch");
55558
55953
  const taskComplete = this.createSwarmTaskCompleteTool(role);
55559
55954
  switch (role) {
55560
55955
  case "researcher": {
@@ -55918,7 +56313,7 @@ INSTRUCTIONS:
55918
56313
  2. Summarize the key learnings and next steps
55919
56314
 
55920
56315
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
55921
- const reportPath = join64(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
56316
+ const reportPath = join65(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
55922
56317
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
55923
56318
 
55924
56319
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -55940,8 +56335,8 @@ ${summaryResult}
55940
56335
  *Generated by open-agents autoresearch swarm*
55941
56336
  `;
55942
56337
  try {
55943
- mkdirSync22(this.dreamsDir, { recursive: true });
55944
- writeFileSync22(reportPath, report, "utf-8");
56338
+ mkdirSync23(this.dreamsDir, { recursive: true });
56339
+ writeFileSync23(reportPath, report, "utf-8");
55945
56340
  } catch {
55946
56341
  }
55947
56342
  renderSwarmComplete(workspace);
@@ -56007,29 +56402,29 @@ ${summaryResult}
56007
56402
  }
56008
56403
  /** Save workspace backup for lucid mode */
56009
56404
  saveVersionCheckpoint(cycle) {
56010
- const checkpointDir = join64(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
56405
+ const checkpointDir = join65(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
56011
56406
  try {
56012
- mkdirSync22(checkpointDir, { recursive: true });
56407
+ mkdirSync23(checkpointDir, { recursive: true });
56013
56408
  try {
56014
- const gitStatus = execSync31("git status --porcelain", {
56409
+ const gitStatus = execSync32("git status --porcelain", {
56015
56410
  cwd: this.repoRoot,
56016
56411
  encoding: "utf-8",
56017
56412
  timeout: 1e4
56018
56413
  });
56019
- const gitDiff = execSync31("git diff", {
56414
+ const gitDiff = execSync32("git diff", {
56020
56415
  cwd: this.repoRoot,
56021
56416
  encoding: "utf-8",
56022
56417
  timeout: 1e4
56023
56418
  });
56024
- const gitHash = execSync31("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
56419
+ const gitHash = execSync32("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
56025
56420
  cwd: this.repoRoot,
56026
56421
  encoding: "utf-8",
56027
56422
  timeout: 5e3
56028
56423
  }).trim();
56029
- writeFileSync22(join64(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
56030
- writeFileSync22(join64(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
56031
- writeFileSync22(join64(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
56032
- writeFileSync22(join64(checkpointDir, "checkpoint.json"), JSON.stringify({
56424
+ writeFileSync23(join65(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
56425
+ writeFileSync23(join65(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
56426
+ writeFileSync23(join65(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
56427
+ writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({
56033
56428
  cycle,
56034
56429
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
56035
56430
  gitHash,
@@ -56037,7 +56432,7 @@ ${summaryResult}
56037
56432
  }, null, 2), "utf-8");
56038
56433
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
56039
56434
  } catch {
56040
- writeFileSync22(join64(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
56435
+ writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
56041
56436
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
56042
56437
  }
56043
56438
  } catch (err) {
@@ -56095,14 +56490,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
56095
56490
  ---
56096
56491
  *Auto-generated by open-agents dream engine*
56097
56492
  `;
56098
- writeFileSync22(join64(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
56493
+ writeFileSync23(join65(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
56099
56494
  } catch {
56100
56495
  }
56101
56496
  }
56102
56497
  /** Save dream state for resume/inspection */
56103
56498
  saveDreamState() {
56104
56499
  try {
56105
- writeFileSync22(join64(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
56500
+ writeFileSync23(join65(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
56106
56501
  } catch {
56107
56502
  }
56108
56503
  }
@@ -56476,8 +56871,8 @@ var init_bless_engine = __esm({
56476
56871
  });
56477
56872
 
56478
56873
  // packages/cli/dist/tui/dmn-engine.js
56479
- import { existsSync as existsSync48, readFileSync as readFileSync37, writeFileSync as writeFileSync23, mkdirSync as mkdirSync23, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
56480
- import { join as join65, basename as basename15 } from "node:path";
56874
+ import { existsSync as existsSync49, readFileSync as readFileSync38, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
56875
+ import { join as join66, basename as basename15 } from "node:path";
56481
56876
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
56482
56877
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
56483
56878
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -56597,9 +56992,9 @@ var init_dmn_engine = __esm({
56597
56992
  constructor(config, repoRoot) {
56598
56993
  this.config = config;
56599
56994
  this.repoRoot = repoRoot;
56600
- this.stateDir = join65(repoRoot, ".oa", "dmn");
56601
- this.historyDir = join65(repoRoot, ".oa", "dmn", "cycles");
56602
- mkdirSync23(this.historyDir, { recursive: true });
56995
+ this.stateDir = join66(repoRoot, ".oa", "dmn");
56996
+ this.historyDir = join66(repoRoot, ".oa", "dmn", "cycles");
56997
+ mkdirSync24(this.historyDir, { recursive: true });
56603
56998
  this.loadState();
56604
56999
  }
56605
57000
  get stats() {
@@ -57188,11 +57583,11 @@ OUTPUT: Call task_complete with JSON:
57188
57583
  async gatherMemoryTopics() {
57189
57584
  const topics = [];
57190
57585
  const dirs = [
57191
- join65(this.repoRoot, ".oa", "memory"),
57192
- join65(this.repoRoot, ".open-agents", "memory")
57586
+ join66(this.repoRoot, ".oa", "memory"),
57587
+ join66(this.repoRoot, ".open-agents", "memory")
57193
57588
  ];
57194
57589
  for (const dir of dirs) {
57195
- if (!existsSync48(dir))
57590
+ if (!existsSync49(dir))
57196
57591
  continue;
57197
57592
  try {
57198
57593
  const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
@@ -57208,29 +57603,29 @@ OUTPUT: Call task_complete with JSON:
57208
57603
  }
57209
57604
  // ── State persistence ─────────────────────────────────────────────────
57210
57605
  loadState() {
57211
- const path = join65(this.stateDir, "state.json");
57212
- if (existsSync48(path)) {
57606
+ const path = join66(this.stateDir, "state.json");
57607
+ if (existsSync49(path)) {
57213
57608
  try {
57214
- this.state = JSON.parse(readFileSync37(path, "utf-8"));
57609
+ this.state = JSON.parse(readFileSync38(path, "utf-8"));
57215
57610
  } catch {
57216
57611
  }
57217
57612
  }
57218
57613
  }
57219
57614
  saveState() {
57220
57615
  try {
57221
- writeFileSync23(join65(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
57616
+ writeFileSync24(join66(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
57222
57617
  } catch {
57223
57618
  }
57224
57619
  }
57225
57620
  saveCycleResult(result) {
57226
57621
  try {
57227
57622
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
57228
- writeFileSync23(join65(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
57623
+ writeFileSync24(join66(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
57229
57624
  const files = readdirSync16(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
57230
57625
  if (files.length > 50) {
57231
57626
  for (const old of files.slice(0, files.length - 50)) {
57232
57627
  try {
57233
- unlinkSync10(join65(this.historyDir, old));
57628
+ unlinkSync10(join66(this.historyDir, old));
57234
57629
  } catch {
57235
57630
  }
57236
57631
  }
@@ -57243,8 +57638,8 @@ OUTPUT: Call task_complete with JSON:
57243
57638
  });
57244
57639
 
57245
57640
  // packages/cli/dist/tui/snr-engine.js
57246
- import { existsSync as existsSync49, readdirSync as readdirSync17, readFileSync as readFileSync38 } from "node:fs";
57247
- import { join as join66, basename as basename16 } from "node:path";
57641
+ import { existsSync as existsSync50, readdirSync as readdirSync17, readFileSync as readFileSync39 } from "node:fs";
57642
+ import { join as join67, basename as basename16 } from "node:path";
57248
57643
  function computeDPrime(signalScores, noiseScores) {
57249
57644
  if (signalScores.length === 0 || noiseScores.length === 0)
57250
57645
  return 0;
@@ -57484,11 +57879,11 @@ Call task_complete with the JSON array when done.`, onEvent)
57484
57879
  loadMemoryEntries(topics) {
57485
57880
  const entries = [];
57486
57881
  const dirs = [
57487
- join66(this.repoRoot, ".oa", "memory"),
57488
- join66(this.repoRoot, ".open-agents", "memory")
57882
+ join67(this.repoRoot, ".oa", "memory"),
57883
+ join67(this.repoRoot, ".open-agents", "memory")
57489
57884
  ];
57490
57885
  for (const dir of dirs) {
57491
- if (!existsSync49(dir))
57886
+ if (!existsSync50(dir))
57492
57887
  continue;
57493
57888
  try {
57494
57889
  const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
@@ -57497,7 +57892,7 @@ Call task_complete with the JSON array when done.`, onEvent)
57497
57892
  if (topics.length > 0 && !topics.includes(topic))
57498
57893
  continue;
57499
57894
  try {
57500
- const data = JSON.parse(readFileSync38(join66(dir, f), "utf-8"));
57895
+ const data = JSON.parse(readFileSync39(join67(dir, f), "utf-8"));
57501
57896
  for (const [key, val] of Object.entries(data)) {
57502
57897
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
57503
57898
  entries.push({ topic, key, value });
@@ -58064,8 +58459,8 @@ var init_tool_policy = __esm({
58064
58459
  });
58065
58460
 
58066
58461
  // packages/cli/dist/tui/telegram-bridge.js
58067
- import { mkdirSync as mkdirSync24, existsSync as existsSync50, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
58068
- import { join as join67, resolve as resolve30 } from "node:path";
58462
+ import { mkdirSync as mkdirSync25, existsSync as existsSync51, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
58463
+ import { join as join68, resolve as resolve30 } from "node:path";
58069
58464
  import { writeFile as writeFileAsync } from "node:fs/promises";
58070
58465
  function convertMarkdownToTelegramHTML(md) {
58071
58466
  let html = md;
@@ -58393,7 +58788,7 @@ with summary "no_reply" to silently skip without responding.
58393
58788
  this.polling = true;
58394
58789
  this.abortController = new AbortController();
58395
58790
  try {
58396
- mkdirSync24(this.mediaCacheDir, { recursive: true });
58791
+ mkdirSync25(this.mediaCacheDir, { recursive: true });
58397
58792
  } catch {
58398
58793
  }
58399
58794
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -58830,7 +59225,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
58830
59225
  return null;
58831
59226
  const buffer = Buffer.from(await res.arrayBuffer());
58832
59227
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
58833
- const localPath = join67(this.mediaCacheDir, fileName);
59228
+ const localPath = join68(this.mediaCacheDir, fileName);
58834
59229
  await writeFileAsync(localPath, buffer);
58835
59230
  return localPath;
58836
59231
  } catch {
@@ -59846,7 +60241,7 @@ __export(text_selection_exports, {
59846
60241
  stripAnsi: () => stripAnsi3,
59847
60242
  visibleLength: () => visibleLength
59848
60243
  });
59849
- import { execSync as execSync32 } from "node:child_process";
60244
+ import { execSync as execSync33 } from "node:child_process";
59850
60245
  function stripAnsi3(s) {
59851
60246
  return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
59852
60247
  }
@@ -59857,16 +60252,16 @@ function copyText(text) {
59857
60252
  try {
59858
60253
  const platform6 = process.platform;
59859
60254
  if (platform6 === "darwin") {
59860
- execSync32("pbcopy", { input: text, timeout: 3e3 });
60255
+ execSync33("pbcopy", { input: text, timeout: 3e3 });
59861
60256
  return true;
59862
60257
  }
59863
60258
  if (platform6 === "win32") {
59864
- execSync32("clip", { input: text, timeout: 3e3 });
60259
+ execSync33("clip", { input: text, timeout: 3e3 });
59865
60260
  return true;
59866
60261
  }
59867
60262
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
59868
60263
  try {
59869
- execSync32(tool, { input: text, timeout: 3e3 });
60264
+ execSync33(tool, { input: text, timeout: 3e3 });
59870
60265
  return true;
59871
60266
  } catch {
59872
60267
  continue;
@@ -59875,10 +60270,10 @@ function copyText(text) {
59875
60270
  if (!_clipboardAutoInstallAttempted) {
59876
60271
  _clipboardAutoInstallAttempted = true;
59877
60272
  try {
59878
- execSync32("which apt-get", { timeout: 2e3, stdio: "pipe" });
60273
+ execSync33("which apt-get", { timeout: 2e3, stdio: "pipe" });
59879
60274
  try {
59880
- execSync32("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
59881
- execSync32("xclip -selection clipboard", { input: text, timeout: 3e3 });
60275
+ execSync33("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
60276
+ execSync33("xclip -selection clipboard", { input: text, timeout: 3e3 });
59882
60277
  return true;
59883
60278
  } catch {
59884
60279
  }
@@ -60186,7 +60581,7 @@ var init_text_selection = __esm({
60186
60581
  });
60187
60582
 
60188
60583
  // packages/cli/dist/tui/status-bar.js
60189
- import { readFileSync as readFileSync39 } from "node:fs";
60584
+ import { readFileSync as readFileSync40 } from "node:fs";
60190
60585
  function setTerminalTitle(task, version) {
60191
60586
  if (!process.stdout.isTTY)
60192
60587
  return;
@@ -60883,7 +61278,7 @@ var init_status_bar = __esm({
60883
61278
  if (nexusDir) {
60884
61279
  try {
60885
61280
  const metricsPath = nexusDir + "/remote-metrics.json";
60886
- const raw = readFileSync39(metricsPath, "utf8");
61281
+ const raw = readFileSync40(metricsPath, "utf8");
60887
61282
  const cached = JSON.parse(raw);
60888
61283
  if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
60889
61284
  const m = cached.data;
@@ -63176,24 +63571,24 @@ var init_direct_input = __esm({
63176
63571
  });
63177
63572
 
63178
63573
  // packages/cli/dist/api/profiles.js
63179
- import { existsSync as existsSync51, readFileSync as readFileSync40, writeFileSync as writeFileSync24, mkdirSync as mkdirSync25, readdirSync as readdirSync19, unlinkSync as unlinkSync12 } from "node:fs";
63180
- import { join as join68 } from "node:path";
63181
- import { homedir as homedir17 } from "node:os";
63574
+ import { existsSync as existsSync52, readFileSync as readFileSync41, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26, readdirSync as readdirSync19, unlinkSync as unlinkSync12 } from "node:fs";
63575
+ import { join as join69 } from "node:path";
63576
+ import { homedir as homedir18 } from "node:os";
63182
63577
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
63183
63578
  function globalProfileDir() {
63184
- return join68(homedir17(), ".open-agents", "profiles");
63579
+ return join69(homedir18(), ".open-agents", "profiles");
63185
63580
  }
63186
63581
  function projectProfileDir(projectDir) {
63187
- return join68(projectDir || process.cwd(), ".oa", "profiles");
63582
+ return join69(projectDir || process.cwd(), ".oa", "profiles");
63188
63583
  }
63189
63584
  function listProfiles(projectDir) {
63190
63585
  const result = [];
63191
63586
  const seen = /* @__PURE__ */ new Set();
63192
63587
  const projDir = projectProfileDir(projectDir);
63193
- if (existsSync51(projDir)) {
63588
+ if (existsSync52(projDir)) {
63194
63589
  for (const f of readdirSync19(projDir).filter((f2) => f2.endsWith(".json"))) {
63195
63590
  try {
63196
- const raw = JSON.parse(readFileSync40(join68(projDir, f), "utf8"));
63591
+ const raw = JSON.parse(readFileSync41(join69(projDir, f), "utf8"));
63197
63592
  const name = f.replace(".json", "");
63198
63593
  seen.add(name);
63199
63594
  result.push({
@@ -63207,13 +63602,13 @@ function listProfiles(projectDir) {
63207
63602
  }
63208
63603
  }
63209
63604
  const globDir = globalProfileDir();
63210
- if (existsSync51(globDir)) {
63605
+ if (existsSync52(globDir)) {
63211
63606
  for (const f of readdirSync19(globDir).filter((f2) => f2.endsWith(".json"))) {
63212
63607
  const name = f.replace(".json", "");
63213
63608
  if (seen.has(name))
63214
63609
  continue;
63215
63610
  try {
63216
- const raw = JSON.parse(readFileSync40(join68(globDir, f), "utf8"));
63611
+ const raw = JSON.parse(readFileSync41(join69(globDir, f), "utf8"));
63217
63612
  result.push({
63218
63613
  name,
63219
63614
  description: raw.description || "",
@@ -63228,12 +63623,12 @@ function listProfiles(projectDir) {
63228
63623
  }
63229
63624
  function loadProfile(name, password, projectDir) {
63230
63625
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
63231
- const projPath = join68(projectProfileDir(projectDir), `${sanitized}.json`);
63232
- const globPath = join68(globalProfileDir(), `${sanitized}.json`);
63233
- const filePath = existsSync51(projPath) ? projPath : existsSync51(globPath) ? globPath : null;
63626
+ const projPath = join69(projectProfileDir(projectDir), `${sanitized}.json`);
63627
+ const globPath = join69(globalProfileDir(), `${sanitized}.json`);
63628
+ const filePath = existsSync52(projPath) ? projPath : existsSync52(globPath) ? globPath : null;
63234
63629
  if (!filePath)
63235
63630
  return null;
63236
- const raw = JSON.parse(readFileSync40(filePath, "utf8"));
63631
+ const raw = JSON.parse(readFileSync41(filePath, "utf8"));
63237
63632
  if (raw.encrypted === true) {
63238
63633
  if (!password)
63239
63634
  return null;
@@ -63243,23 +63638,23 @@ function loadProfile(name, password, projectDir) {
63243
63638
  }
63244
63639
  function saveProfile(profile, password, scope = "global", projectDir) {
63245
63640
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
63246
- mkdirSync25(dir, { recursive: true });
63641
+ mkdirSync26(dir, { recursive: true });
63247
63642
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
63248
- const filePath = join68(dir, `${sanitized}.json`);
63643
+ const filePath = join69(dir, `${sanitized}.json`);
63249
63644
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
63250
63645
  if (password) {
63251
63646
  const encrypted = encryptProfile(profile, password);
63252
- writeFileSync24(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
63647
+ writeFileSync25(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
63253
63648
  } else {
63254
63649
  profile.encrypted = false;
63255
- writeFileSync24(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
63650
+ writeFileSync25(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
63256
63651
  }
63257
63652
  }
63258
63653
  function deleteProfile(name, scope = "global", projectDir) {
63259
63654
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
63260
63655
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
63261
- const filePath = join68(dir, `${sanitized}.json`);
63262
- if (existsSync51(filePath)) {
63656
+ const filePath = join69(dir, `${sanitized}.json`);
63657
+ if (existsSync52(filePath)) {
63263
63658
  unlinkSync12(filePath);
63264
63659
  return true;
63265
63660
  }
@@ -63352,22 +63747,22 @@ import * as http from "node:http";
63352
63747
  import * as https from "node:https";
63353
63748
  import { createRequire as createRequire3 } from "node:module";
63354
63749
  import { fileURLToPath as fileURLToPath12 } from "node:url";
63355
- import { dirname as dirname20, join as join69, resolve as resolve31 } from "node:path";
63356
- import { spawn as spawn20 } from "node:child_process";
63357
- import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync25, readFileSync as readFileSync41, readdirSync as readdirSync20, existsSync as existsSync52 } from "node:fs";
63750
+ import { dirname as dirname20, join as join70, resolve as resolve31 } from "node:path";
63751
+ import { spawn as spawn21 } from "node:child_process";
63752
+ import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26, readFileSync as readFileSync42, readdirSync as readdirSync20, existsSync as existsSync53 } from "node:fs";
63358
63753
  import { randomBytes as randomBytes16 } from "node:crypto";
63359
63754
  function getVersion3() {
63360
63755
  try {
63361
63756
  const require2 = createRequire3(import.meta.url);
63362
63757
  const thisDir = dirname20(fileURLToPath12(import.meta.url));
63363
63758
  const candidates = [
63364
- join69(thisDir, "..", "package.json"),
63365
- join69(thisDir, "..", "..", "package.json"),
63366
- join69(thisDir, "..", "..", "..", "package.json")
63759
+ join70(thisDir, "..", "package.json"),
63760
+ join70(thisDir, "..", "..", "package.json"),
63761
+ join70(thisDir, "..", "..", "..", "package.json")
63367
63762
  ];
63368
63763
  for (const pkgPath of candidates) {
63369
63764
  try {
63370
- if (!existsSync52(pkgPath))
63765
+ if (!existsSync53(pkgPath))
63371
63766
  continue;
63372
63767
  const pkg = require2(pkgPath);
63373
63768
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
@@ -63662,29 +64057,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
63662
64057
  }
63663
64058
  function jobsDir() {
63664
64059
  const root = resolve31(process.cwd());
63665
- const dir = join69(root, ".oa", "jobs");
63666
- mkdirSync26(dir, { recursive: true });
64060
+ const dir = join70(root, ".oa", "jobs");
64061
+ mkdirSync27(dir, { recursive: true });
63667
64062
  return dir;
63668
64063
  }
63669
64064
  function loadJob(id) {
63670
- const file = join69(jobsDir(), `${id}.json`);
63671
- if (!existsSync52(file))
64065
+ const file = join70(jobsDir(), `${id}.json`);
64066
+ if (!existsSync53(file))
63672
64067
  return null;
63673
64068
  try {
63674
- return JSON.parse(readFileSync41(file, "utf-8"));
64069
+ return JSON.parse(readFileSync42(file, "utf-8"));
63675
64070
  } catch {
63676
64071
  return null;
63677
64072
  }
63678
64073
  }
63679
64074
  function listJobs() {
63680
64075
  const dir = jobsDir();
63681
- if (!existsSync52(dir))
64076
+ if (!existsSync53(dir))
63682
64077
  return [];
63683
64078
  const files = readdirSync20(dir).filter((f) => f.endsWith(".json")).sort();
63684
64079
  const jobs = [];
63685
64080
  for (const file of files) {
63686
64081
  try {
63687
- jobs.push(JSON.parse(readFileSync41(join69(dir, file), "utf-8")));
64082
+ jobs.push(JSON.parse(readFileSync42(join70(dir, file), "utf-8")));
63688
64083
  } catch {
63689
64084
  }
63690
64085
  }
@@ -64077,8 +64472,8 @@ async function handleV1Run(req, res) {
64077
64472
  if (workingDir) {
64078
64473
  cwd4 = resolve31(workingDir);
64079
64474
  } else if (isolate) {
64080
- const wsDir = join69(dir, "..", "workspaces", id);
64081
- mkdirSync26(wsDir, { recursive: true });
64475
+ const wsDir = join70(dir, "..", "workspaces", id);
64476
+ mkdirSync27(wsDir, { recursive: true });
64082
64477
  cwd4 = wsDir;
64083
64478
  } else {
64084
64479
  cwd4 = resolve31(process.cwd());
@@ -64142,7 +64537,7 @@ async function handleV1Run(req, res) {
64142
64537
  }
64143
64538
  }
64144
64539
  }
64145
- const child = spawn20("node", [oaBin, ...args], {
64540
+ const child = spawn21("node", [oaBin, ...args], {
64146
64541
  cwd: cwd4,
64147
64542
  env: runEnv,
64148
64543
  stdio: ["ignore", "pipe", "pipe"],
@@ -64150,7 +64545,7 @@ async function handleV1Run(req, res) {
64150
64545
  });
64151
64546
  child.unref();
64152
64547
  job.pid = child.pid ?? 0;
64153
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
64548
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64154
64549
  runningProcesses.set(id, child);
64155
64550
  if (streamMode) {
64156
64551
  res.writeHead(200, {
@@ -64180,7 +64575,7 @@ async function handleV1Run(req, res) {
64180
64575
  job.status = code === 0 ? "completed" : "failed";
64181
64576
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
64182
64577
  try {
64183
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
64578
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64184
64579
  } catch {
64185
64580
  }
64186
64581
  runningProcesses.delete(id);
@@ -64211,7 +64606,7 @@ async function handleV1Run(req, res) {
64211
64606
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
64212
64607
  }
64213
64608
  try {
64214
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
64609
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64215
64610
  } catch {
64216
64611
  }
64217
64612
  runningProcesses.delete(id);
@@ -64252,7 +64647,7 @@ function handleV1RunsDelete(res, id) {
64252
64647
  job.error = "Aborted via API";
64253
64648
  const dir = jobsDir();
64254
64649
  try {
64255
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
64650
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64256
64651
  } catch {
64257
64652
  }
64258
64653
  runningProcesses.delete(id);
@@ -64364,7 +64759,7 @@ async function handlePostCommand(res, cmd) {
64364
64759
  return;
64365
64760
  }
64366
64761
  try {
64367
- const child = spawn20("node", [oaBin, "run", `/${cmd}`, "--json"], {
64762
+ const child = spawn21("node", [oaBin, "run", `/${cmd}`, "--json"], {
64368
64763
  env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
64369
64764
  stdio: ["ignore", "pipe", "pipe"],
64370
64765
  timeout: 3e4
@@ -64777,13 +65172,13 @@ var init_serve = __esm({
64777
65172
 
64778
65173
  // packages/cli/dist/tui/interactive.js
64779
65174
  import { cwd } from "node:process";
64780
- import { resolve as resolve32, join as join70, dirname as dirname21, extname as extname11 } from "node:path";
65175
+ import { resolve as resolve32, join as join71, dirname as dirname21, extname as extname11 } from "node:path";
64781
65176
  import { createRequire as createRequire4 } from "node:module";
64782
65177
  import { fileURLToPath as fileURLToPath13 } from "node:url";
64783
- import { readFileSync as readFileSync42, writeFileSync as writeFileSync26, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync21, mkdirSync as mkdirSync27 } from "node:fs";
64784
- import { existsSync as existsSync53 } from "node:fs";
64785
- import { execSync as execSync33 } from "node:child_process";
64786
- import { homedir as homedir18 } from "node:os";
65178
+ import { readFileSync as readFileSync43, writeFileSync as writeFileSync27, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync21, mkdirSync as mkdirSync28 } from "node:fs";
65179
+ import { existsSync as existsSync54 } from "node:fs";
65180
+ import { execSync as execSync34 } from "node:child_process";
65181
+ import { homedir as homedir19 } from "node:os";
64787
65182
  function formatTimeAgo(date) {
64788
65183
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
64789
65184
  if (seconds < 60)
@@ -64802,12 +65197,12 @@ function getVersion4() {
64802
65197
  const require2 = createRequire4(import.meta.url);
64803
65198
  const thisDir = dirname21(fileURLToPath13(import.meta.url));
64804
65199
  const candidates = [
64805
- join70(thisDir, "..", "package.json"),
64806
- join70(thisDir, "..", "..", "package.json"),
64807
- join70(thisDir, "..", "..", "..", "package.json")
65200
+ join71(thisDir, "..", "package.json"),
65201
+ join71(thisDir, "..", "..", "package.json"),
65202
+ join71(thisDir, "..", "..", "..", "package.json")
64808
65203
  ];
64809
65204
  for (const pkgPath of candidates) {
64810
- if (existsSync53(pkgPath)) {
65205
+ if (existsSync54(pkgPath)) {
64811
65206
  const pkg = require2(pkgPath);
64812
65207
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
64813
65208
  return pkg.version ?? "0.0.0";
@@ -65043,15 +65438,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
65043
65438
  function gatherMemorySnippets(root) {
65044
65439
  const snippets = [];
65045
65440
  const dirs = [
65046
- join70(root, ".oa", "memory"),
65047
- join70(root, ".open-agents", "memory")
65441
+ join71(root, ".oa", "memory"),
65442
+ join71(root, ".open-agents", "memory")
65048
65443
  ];
65049
65444
  for (const dir of dirs) {
65050
- if (!existsSync53(dir))
65445
+ if (!existsSync54(dir))
65051
65446
  continue;
65052
65447
  try {
65053
65448
  for (const f of readdirSync21(dir).filter((f2) => f2.endsWith(".json"))) {
65054
- const data = JSON.parse(readFileSync42(join70(dir, f), "utf-8"));
65449
+ const data = JSON.parse(readFileSync43(join71(dir, f), "utf-8"));
65055
65450
  for (const val of Object.values(data)) {
65056
65451
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
65057
65452
  if (v.length > 10)
@@ -65208,9 +65603,9 @@ ${metabolismMemories}
65208
65603
  } catch {
65209
65604
  }
65210
65605
  try {
65211
- const archeFile = join70(repoRoot, ".oa", "arche", "variants.json");
65212
- if (existsSync53(archeFile)) {
65213
- const variants = JSON.parse(readFileSync42(archeFile, "utf8"));
65606
+ const archeFile = join71(repoRoot, ".oa", "arche", "variants.json");
65607
+ if (existsSync54(archeFile)) {
65608
+ const variants = JSON.parse(readFileSync43(archeFile, "utf8"));
65214
65609
  if (variants.length > 0) {
65215
65610
  let filtered = variants;
65216
65611
  if (taskType) {
@@ -65379,9 +65774,9 @@ RULES:
65379
65774
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
65380
65775
  let identityInjection = "";
65381
65776
  try {
65382
- const ikStateFile = join70(repoRoot, ".oa", "identity", "self-state.json");
65383
- if (existsSync53(ikStateFile)) {
65384
- const selfState = JSON.parse(readFileSync42(ikStateFile, "utf8"));
65777
+ const ikStateFile = join71(repoRoot, ".oa", "identity", "self-state.json");
65778
+ if (existsSync54(ikStateFile)) {
65779
+ const selfState = JSON.parse(readFileSync43(ikStateFile, "utf8"));
65385
65780
  const lines = [
65386
65781
  `[Identity State v${selfState.version}]`,
65387
65782
  `Self: ${selfState.narrative_summary}`,
@@ -66024,13 +66419,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66024
66419
  });
66025
66420
  }
66026
66421
  try {
66027
- const ikDir = join70(repoRoot, ".oa", "identity");
66028
- const ikFile = join70(ikDir, "self-state.json");
66422
+ const ikDir = join71(repoRoot, ".oa", "identity");
66423
+ const ikFile = join71(ikDir, "self-state.json");
66029
66424
  let ikState;
66030
- if (existsSync53(ikFile)) {
66031
- ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
66425
+ if (existsSync54(ikFile)) {
66426
+ ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
66032
66427
  } else {
66033
- mkdirSync27(ikDir, { recursive: true });
66428
+ mkdirSync28(ikDir, { recursive: true });
66034
66429
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
66035
66430
  ikState = {
66036
66431
  self_id: `oa-${machineId}`,
@@ -66056,7 +66451,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66056
66451
  }
66057
66452
  ikState.session_count = (ikState.session_count || 0) + 1;
66058
66453
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
66059
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
66454
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
66060
66455
  } catch (ikErr) {
66061
66456
  try {
66062
66457
  console.error("[IK-OBSERVE]", ikErr);
@@ -66071,14 +66466,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66071
66466
  } else {
66072
66467
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
66073
66468
  try {
66074
- const ikFile = join70(repoRoot, ".oa", "identity", "self-state.json");
66075
- if (existsSync53(ikFile)) {
66076
- const ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
66469
+ const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
66470
+ if (existsSync54(ikFile)) {
66471
+ const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
66077
66472
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
66078
66473
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
66079
66474
  ikState.session_count = (ikState.session_count || 0) + 1;
66080
66475
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
66081
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
66476
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
66082
66477
  }
66083
66478
  } catch {
66084
66479
  }
@@ -66175,10 +66570,10 @@ async function startInteractive(config, repoPath) {
66175
66570
  process.stdin.pause();
66176
66571
  }
66177
66572
  try {
66178
- const oaDir = join70(repoRoot, ".oa");
66179
- const nexusPidFile = join70(oaDir, "nexus", "daemon.pid");
66180
- if (existsSync53(nexusPidFile)) {
66181
- const pid = parseInt(readFileSync42(nexusPidFile, "utf8").trim(), 10);
66573
+ const oaDir = join71(repoRoot, ".oa");
66574
+ const nexusPidFile = join71(oaDir, "nexus", "daemon.pid");
66575
+ if (existsSync54(nexusPidFile)) {
66576
+ const pid = parseInt(readFileSync43(nexusPidFile, "utf8").trim(), 10);
66182
66577
  if (pid > 0) {
66183
66578
  try {
66184
66579
  process.kill(pid, 0);
@@ -66487,7 +66882,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
66487
66882
  let p2pGateway = null;
66488
66883
  let peerMesh = null;
66489
66884
  let inferenceRouter = null;
66490
- const secretVault = new SecretVault(join70(repoRoot, ".oa", "vault.enc"));
66885
+ const secretVault = new SecretVault(join71(repoRoot, ".oa", "vault.enc"));
66491
66886
  let adminSessionKey = null;
66492
66887
  const callSubAgents = /* @__PURE__ */ new Map();
66493
66888
  const streamRenderer = new StreamRenderer();
@@ -66710,13 +67105,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
66710
67105
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
66711
67106
  return [hits, line];
66712
67107
  }
66713
- const HISTORY_DIR = join70(homedir18(), ".open-agents");
66714
- const HISTORY_FILE = join70(HISTORY_DIR, "repl-history");
67108
+ const HISTORY_DIR = join71(homedir19(), ".open-agents");
67109
+ const HISTORY_FILE = join71(HISTORY_DIR, "repl-history");
66715
67110
  const MAX_HISTORY_LINES = 500;
66716
67111
  let savedHistory = [];
66717
67112
  try {
66718
- if (existsSync53(HISTORY_FILE)) {
66719
- const raw = readFileSync42(HISTORY_FILE, "utf8").trim();
67113
+ if (existsSync54(HISTORY_FILE)) {
67114
+ const raw = readFileSync43(HISTORY_FILE, "utf8").trim();
66720
67115
  if (raw)
66721
67116
  savedHistory = raw.split("\n").reverse();
66722
67117
  }
@@ -66819,12 +67214,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
66819
67214
  if (!line.trim())
66820
67215
  return;
66821
67216
  try {
66822
- mkdirSync27(HISTORY_DIR, { recursive: true });
67217
+ mkdirSync28(HISTORY_DIR, { recursive: true });
66823
67218
  appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
66824
67219
  if (Math.random() < 0.02) {
66825
- const all = readFileSync42(HISTORY_FILE, "utf8").trim().split("\n");
67220
+ const all = readFileSync43(HISTORY_FILE, "utf8").trim().split("\n");
66826
67221
  if (all.length > MAX_HISTORY_LINES) {
66827
- writeFileSync26(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
67222
+ writeFileSync27(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
66828
67223
  }
66829
67224
  }
66830
67225
  } catch {
@@ -67008,7 +67403,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67008
67403
  } catch {
67009
67404
  }
67010
67405
  try {
67011
- const oaDir = join70(repoRoot, ".oa");
67406
+ const oaDir = join71(repoRoot, ".oa");
67012
67407
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
67013
67408
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
67014
67409
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -67040,7 +67435,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67040
67435
  } catch {
67041
67436
  }
67042
67437
  try {
67043
- const oaDir = join70(repoRoot, ".oa");
67438
+ const oaDir = join71(repoRoot, ".oa");
67044
67439
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
67045
67440
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
67046
67441
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -67081,11 +67476,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67081
67476
  }
67082
67477
  try {
67083
67478
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
67084
- const globalNamePath = join70(_hd(), ".open-agents", "agent-name");
67479
+ const globalNamePath = join71(_hd(), ".open-agents", "agent-name");
67085
67480
  let agName = "";
67086
67481
  try {
67087
- if (existsSync53(globalNamePath))
67088
- agName = readFileSync42(globalNamePath, "utf8").trim();
67482
+ if (existsSync54(globalNamePath))
67483
+ agName = readFileSync43(globalNamePath, "utf8").trim();
67089
67484
  } catch {
67090
67485
  }
67091
67486
  if (!agName) {
@@ -68050,7 +68445,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68050
68445
  kind,
68051
68446
  targetUrl,
68052
68447
  authKey,
68053
- stateDir: join70(repoRoot, ".oa"),
68448
+ stateDir: join71(repoRoot, ".oa"),
68054
68449
  passthrough: passthrough ?? false,
68055
68450
  loadbalance: loadbalance ?? false,
68056
68451
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -68098,7 +68493,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68098
68493
  await tunnelGateway.stop();
68099
68494
  tunnelGateway = null;
68100
68495
  }
68101
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join70(repoRoot, ".oa") });
68496
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join71(repoRoot, ".oa") });
68102
68497
  newTunnel.on("stats", (stats) => {
68103
68498
  statusBar.setExposeStatus({
68104
68499
  status: stats.status,
@@ -68370,15 +68765,15 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68370
68765
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
68371
68766
  }
68372
68767
  try {
68373
- const nexusDir = join70(repoRoot, OA_DIR, "nexus");
68374
- const pidFile = join70(nexusDir, "daemon.pid");
68375
- if (existsSync53(pidFile)) {
68376
- const pid = parseInt(readFileSync42(pidFile, "utf8").trim(), 10);
68768
+ const nexusDir = join71(repoRoot, OA_DIR, "nexus");
68769
+ const pidFile = join71(nexusDir, "daemon.pid");
68770
+ if (existsSync54(pidFile)) {
68771
+ const pid = parseInt(readFileSync43(pidFile, "utf8").trim(), 10);
68377
68772
  if (pid > 0) {
68378
68773
  try {
68379
68774
  if (process.platform === "win32") {
68380
68775
  try {
68381
- execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68776
+ execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68382
68777
  } catch {
68383
68778
  }
68384
68779
  } else {
@@ -68395,17 +68790,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68395
68790
  } catch {
68396
68791
  }
68397
68792
  try {
68398
- const voiceDir2 = join70(homedir18(), ".open-agents", "voice");
68793
+ const voiceDir2 = join71(homedir19(), ".open-agents", "voice");
68399
68794
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
68400
68795
  for (const pf of voicePidFiles) {
68401
- const pidPath = join70(voiceDir2, pf);
68402
- if (existsSync53(pidPath)) {
68796
+ const pidPath = join71(voiceDir2, pf);
68797
+ if (existsSync54(pidPath)) {
68403
68798
  try {
68404
- const pid = parseInt(readFileSync42(pidPath, "utf8").trim(), 10);
68799
+ const pid = parseInt(readFileSync43(pidPath, "utf8").trim(), 10);
68405
68800
  if (pid > 0) {
68406
68801
  if (process.platform === "win32") {
68407
68802
  try {
68408
- execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68803
+ execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68409
68804
  } catch {
68410
68805
  }
68411
68806
  } else {
@@ -68422,11 +68817,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68422
68817
  } catch {
68423
68818
  }
68424
68819
  try {
68425
- execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
68820
+ execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
68426
68821
  } catch {
68427
68822
  }
68428
- const oaPath = join70(repoRoot, OA_DIR);
68429
- if (existsSync53(oaPath)) {
68823
+ const oaPath = join71(repoRoot, OA_DIR);
68824
+ if (existsSync54(oaPath)) {
68430
68825
  let deleted = false;
68431
68826
  for (let attempt = 0; attempt < 3; attempt++) {
68432
68827
  try {
@@ -68436,14 +68831,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68436
68831
  } catch (err) {
68437
68832
  if (attempt < 2) {
68438
68833
  try {
68439
- execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
68834
+ execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
68440
68835
  } catch {
68441
68836
  }
68442
68837
  } else {
68443
68838
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
68444
68839
  if (process.platform === "win32") {
68445
68840
  try {
68446
- execSync33(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
68841
+ execSync34(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
68447
68842
  deleted = true;
68448
68843
  } catch {
68449
68844
  }
@@ -68836,8 +69231,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
68836
69231
  }
68837
69232
  }
68838
69233
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
68839
- const isImage = isImagePath(cleanPath) && existsSync53(resolve32(repoRoot, cleanPath));
68840
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync53(resolve32(repoRoot, cleanPath));
69234
+ const isImage = isImagePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
69235
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
68841
69236
  if (activeTask) {
68842
69237
  if (activeTask.runner.isPaused) {
68843
69238
  activeTask.runner.resume();
@@ -68846,7 +69241,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
68846
69241
  if (isImage) {
68847
69242
  try {
68848
69243
  const imgPath = resolve32(repoRoot, cleanPath);
68849
- const imgBuffer = readFileSync42(imgPath);
69244
+ const imgBuffer = readFileSync43(imgPath);
68850
69245
  const base64 = imgBuffer.toString("base64");
68851
69246
  const ext = extname11(cleanPath).toLowerCase();
68852
69247
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -69374,13 +69769,13 @@ async function runWithTUI(task, config, repoPath) {
69374
69769
  const handle = startTask(task, config, repoRoot);
69375
69770
  await handle.promise;
69376
69771
  try {
69377
- const ikDir = join70(repoRoot, ".oa", "identity");
69378
- const ikFile = join70(ikDir, "self-state.json");
69772
+ const ikDir = join71(repoRoot, ".oa", "identity");
69773
+ const ikFile = join71(ikDir, "self-state.json");
69379
69774
  let ikState;
69380
- if (existsSync53(ikFile)) {
69381
- ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
69775
+ if (existsSync54(ikFile)) {
69776
+ ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
69382
69777
  } else {
69383
- mkdirSync27(ikDir, { recursive: true });
69778
+ mkdirSync28(ikDir, { recursive: true });
69384
69779
  ikState = {
69385
69780
  self_id: `oa-${Date.now().toString(36)}`,
69386
69781
  version: 1,
@@ -69402,7 +69797,7 @@ async function runWithTUI(task, config, repoPath) {
69402
69797
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
69403
69798
  ikState.session_count = (ikState.session_count || 0) + 1;
69404
69799
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69405
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
69800
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69406
69801
  } catch (ikErr) {
69407
69802
  }
69408
69803
  try {
@@ -69411,12 +69806,12 @@ async function runWithTUI(task, config, repoPath) {
69411
69806
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
69412
69807
  } catch {
69413
69808
  try {
69414
- const archeDir = join70(repoRoot, ".oa", "arche");
69415
- const archeFile = join70(archeDir, "variants.json");
69809
+ const archeDir = join71(repoRoot, ".oa", "arche");
69810
+ const archeFile = join71(archeDir, "variants.json");
69416
69811
  let variants = [];
69417
69812
  try {
69418
- if (existsSync53(archeFile))
69419
- variants = JSON.parse(readFileSync42(archeFile, "utf8"));
69813
+ if (existsSync54(archeFile))
69814
+ variants = JSON.parse(readFileSync43(archeFile, "utf8"));
69420
69815
  } catch {
69421
69816
  }
69422
69817
  variants.push({
@@ -69431,15 +69826,15 @@ async function runWithTUI(task, config, repoPath) {
69431
69826
  });
69432
69827
  if (variants.length > 50)
69433
69828
  variants = variants.slice(-50);
69434
- mkdirSync27(archeDir, { recursive: true });
69435
- writeFileSync26(archeFile, JSON.stringify(variants, null, 2));
69829
+ mkdirSync28(archeDir, { recursive: true });
69830
+ writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
69436
69831
  } catch {
69437
69832
  }
69438
69833
  }
69439
69834
  try {
69440
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69441
- if (existsSync53(metaFile)) {
69442
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
69835
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
69836
+ if (existsSync54(metaFile)) {
69837
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69443
69838
  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);
69444
69839
  let updated = false;
69445
69840
  for (const item of surfaced) {
@@ -69450,7 +69845,7 @@ async function runWithTUI(task, config, repoPath) {
69450
69845
  updated = true;
69451
69846
  }
69452
69847
  if (updated) {
69453
- writeFileSync26(metaFile, JSON.stringify(store, null, 2));
69848
+ writeFileSync27(metaFile, JSON.stringify(store, null, 2));
69454
69849
  }
69455
69850
  }
69456
69851
  } catch {
@@ -69503,9 +69898,9 @@ Rules:
69503
69898
  try {
69504
69899
  const { initDb: initDb2 } = __require("@open-agents/memory");
69505
69900
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
69506
- const dbDir = join70(repoRoot, ".oa", "memory");
69507
- mkdirSync27(dbDir, { recursive: true });
69508
- const db = initDb2(join70(dbDir, "structured.db"));
69901
+ const dbDir = join71(repoRoot, ".oa", "memory");
69902
+ mkdirSync28(dbDir, { recursive: true });
69903
+ const db = initDb2(join71(dbDir, "structured.db"));
69509
69904
  const memStore = new ProceduralMemoryStore2(db);
69510
69905
  memStore.createWithEmbedding({
69511
69906
  content: content.slice(0, 600),
@@ -69520,12 +69915,12 @@ Rules:
69520
69915
  db.close();
69521
69916
  } catch {
69522
69917
  }
69523
- const metaDir = join70(repoRoot, ".oa", "memory", "metabolism");
69524
- const storeFile = join70(metaDir, "store.json");
69918
+ const metaDir = join71(repoRoot, ".oa", "memory", "metabolism");
69919
+ const storeFile = join71(metaDir, "store.json");
69525
69920
  let store = [];
69526
69921
  try {
69527
- if (existsSync53(storeFile))
69528
- store = JSON.parse(readFileSync42(storeFile, "utf8"));
69922
+ if (existsSync54(storeFile))
69923
+ store = JSON.parse(readFileSync43(storeFile, "utf8"));
69529
69924
  } catch {
69530
69925
  }
69531
69926
  store.push({
@@ -69541,26 +69936,26 @@ Rules:
69541
69936
  });
69542
69937
  if (store.length > 100)
69543
69938
  store = store.slice(-100);
69544
- mkdirSync27(metaDir, { recursive: true });
69545
- writeFileSync26(storeFile, JSON.stringify(store, null, 2));
69939
+ mkdirSync28(metaDir, { recursive: true });
69940
+ writeFileSync27(storeFile, JSON.stringify(store, null, 2));
69546
69941
  }
69547
69942
  }
69548
69943
  } catch {
69549
69944
  }
69550
69945
  try {
69551
- const cohereSettingsFile = join70(repoRoot, ".oa", "settings.json");
69946
+ const cohereSettingsFile = join71(repoRoot, ".oa", "settings.json");
69552
69947
  let cohereActive = false;
69553
69948
  try {
69554
- if (existsSync53(cohereSettingsFile)) {
69555
- const settings = JSON.parse(readFileSync42(cohereSettingsFile, "utf8"));
69949
+ if (existsSync54(cohereSettingsFile)) {
69950
+ const settings = JSON.parse(readFileSync43(cohereSettingsFile, "utf8"));
69556
69951
  cohereActive = settings.cohere === true;
69557
69952
  }
69558
69953
  } catch {
69559
69954
  }
69560
69955
  if (cohereActive) {
69561
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69562
- if (existsSync53(metaFile)) {
69563
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
69956
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
69957
+ if (existsSync54(metaFile)) {
69958
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69564
69959
  const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
69565
69960
  if (latest && latest.scores?.confidence >= 0.6) {
69566
69961
  try {
@@ -69585,18 +69980,18 @@ Rules:
69585
69980
  }
69586
69981
  } catch (err) {
69587
69982
  try {
69588
- const ikFile = join70(repoRoot, ".oa", "identity", "self-state.json");
69589
- if (existsSync53(ikFile)) {
69590
- const ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
69983
+ const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
69984
+ if (existsSync54(ikFile)) {
69985
+ const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
69591
69986
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
69592
69987
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
69593
69988
  ikState.session_count = (ikState.session_count || 0) + 1;
69594
69989
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69595
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
69990
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69596
69991
  }
69597
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69598
- if (existsSync53(metaFile)) {
69599
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
69992
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
69993
+ if (existsSync54(metaFile)) {
69994
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69600
69995
  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);
69601
69996
  for (const item of surfaced) {
69602
69997
  item.accessCount = (item.accessCount || 0) + 1;
@@ -69604,15 +69999,15 @@ Rules:
69604
69999
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
69605
70000
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
69606
70001
  }
69607
- writeFileSync26(metaFile, JSON.stringify(store, null, 2));
70002
+ writeFileSync27(metaFile, JSON.stringify(store, null, 2));
69608
70003
  }
69609
70004
  try {
69610
- const archeDir = join70(repoRoot, ".oa", "arche");
69611
- const archeFile = join70(archeDir, "variants.json");
70005
+ const archeDir = join71(repoRoot, ".oa", "arche");
70006
+ const archeFile = join71(archeDir, "variants.json");
69612
70007
  let variants = [];
69613
70008
  try {
69614
- if (existsSync53(archeFile))
69615
- variants = JSON.parse(readFileSync42(archeFile, "utf8"));
70009
+ if (existsSync54(archeFile))
70010
+ variants = JSON.parse(readFileSync43(archeFile, "utf8"));
69616
70011
  } catch {
69617
70012
  }
69618
70013
  variants.push({
@@ -69627,8 +70022,8 @@ Rules:
69627
70022
  });
69628
70023
  if (variants.length > 50)
69629
70024
  variants = variants.slice(-50);
69630
- mkdirSync27(archeDir, { recursive: true });
69631
- writeFileSync26(archeFile, JSON.stringify(variants, null, 2));
70025
+ mkdirSync28(archeDir, { recursive: true });
70026
+ writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
69632
70027
  } catch {
69633
70028
  }
69634
70029
  } catch {
@@ -69694,14 +70089,14 @@ __export(run_exports, {
69694
70089
  statusCommand: () => statusCommand
69695
70090
  });
69696
70091
  import { resolve as resolve33 } from "node:path";
69697
- import { spawn as spawn21 } from "node:child_process";
69698
- import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync27, readFileSync as readFileSync43, readdirSync as readdirSync22, existsSync as existsSync54 } from "node:fs";
70092
+ import { spawn as spawn22 } from "node:child_process";
70093
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync28, readFileSync as readFileSync44, readdirSync as readdirSync22, existsSync as existsSync55 } from "node:fs";
69699
70094
  import { randomBytes as randomBytes17 } from "node:crypto";
69700
- import { join as join71 } from "node:path";
70095
+ import { join as join72 } from "node:path";
69701
70096
  function jobsDir2(repoPath) {
69702
70097
  const root = resolve33(repoPath ?? process.cwd());
69703
- const dir = join71(root, ".oa", "jobs");
69704
- mkdirSync28(dir, { recursive: true });
70098
+ const dir = join72(root, ".oa", "jobs");
70099
+ mkdirSync29(dir, { recursive: true });
69705
70100
  return dir;
69706
70101
  }
69707
70102
  async function runCommand(opts, config) {
@@ -69778,7 +70173,7 @@ async function runBackground(task, config, opts) {
69778
70173
  const args = [task, "--json"];
69779
70174
  if (config.model)
69780
70175
  args.push("--model", config.model);
69781
- const child = spawn21("node", [oaBin, ...args], {
70176
+ const child = spawn22("node", [oaBin, ...args], {
69782
70177
  cwd: repoRoot,
69783
70178
  env: { ...process.env, OA_JOB_ID: id },
69784
70179
  stdio: ["ignore", "pipe", "pipe"],
@@ -69786,7 +70181,7 @@ async function runBackground(task, config, opts) {
69786
70181
  });
69787
70182
  child.unref();
69788
70183
  job.pid = child.pid ?? 0;
69789
- writeFileSync27(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
70184
+ writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
69790
70185
  let output = "";
69791
70186
  child.stdout?.on("data", (chunk) => {
69792
70187
  output += chunk.toString();
@@ -69802,7 +70197,7 @@ async function runBackground(task, config, opts) {
69802
70197
  job.summary = result.summary;
69803
70198
  job.durationMs = result.durationMs;
69804
70199
  job.error = result.error;
69805
- writeFileSync27(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
70200
+ writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
69806
70201
  } catch {
69807
70202
  }
69808
70203
  });
@@ -69818,13 +70213,13 @@ async function runBackground(task, config, opts) {
69818
70213
  }
69819
70214
  function statusCommand(jobId, repoPath) {
69820
70215
  const dir = jobsDir2(repoPath);
69821
- const file = join71(dir, `${jobId}.json`);
69822
- if (!existsSync54(file)) {
70216
+ const file = join72(dir, `${jobId}.json`);
70217
+ if (!existsSync55(file)) {
69823
70218
  console.error(`Job not found: ${jobId}`);
69824
70219
  console.log(`Available jobs: oa jobs`);
69825
70220
  process.exit(1);
69826
70221
  }
69827
- const job = JSON.parse(readFileSync43(file, "utf-8"));
70222
+ const job = JSON.parse(readFileSync44(file, "utf-8"));
69828
70223
  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`;
69829
70224
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
69830
70225
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -69847,7 +70242,7 @@ function jobsCommand(repoPath) {
69847
70242
  console.log("Jobs:");
69848
70243
  for (const file of files) {
69849
70244
  try {
69850
- const job = JSON.parse(readFileSync43(join71(dir, file), "utf-8"));
70245
+ const job = JSON.parse(readFileSync44(join72(dir, file), "utf-8"));
69851
70246
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
69852
70247
  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`;
69853
70248
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -69867,7 +70262,7 @@ import { glob } from "glob";
69867
70262
  import ignore from "ignore";
69868
70263
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
69869
70264
  import { createHash as createHash6 } from "node:crypto";
69870
- import { join as join72, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
70265
+ import { join as join73, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
69871
70266
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
69872
70267
  var init_codebase_indexer = __esm({
69873
70268
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -69911,7 +70306,7 @@ var init_codebase_indexer = __esm({
69911
70306
  const ig = ignore.default();
69912
70307
  if (this.config.respectGitignore) {
69913
70308
  try {
69914
- const gitignoreContent = await readFile23(join72(this.config.rootDir, ".gitignore"), "utf-8");
70309
+ const gitignoreContent = await readFile23(join73(this.config.rootDir, ".gitignore"), "utf-8");
69915
70310
  ig.add(gitignoreContent);
69916
70311
  } catch {
69917
70312
  }
@@ -69926,7 +70321,7 @@ var init_codebase_indexer = __esm({
69926
70321
  for (const relativePath of files) {
69927
70322
  if (ig.ignores(relativePath))
69928
70323
  continue;
69929
- const fullPath = join72(this.config.rootDir, relativePath);
70324
+ const fullPath = join73(this.config.rootDir, relativePath);
69930
70325
  try {
69931
70326
  const fileStat = await stat4(fullPath);
69932
70327
  if (fileStat.size > this.config.maxFileSize)
@@ -69972,7 +70367,7 @@ var init_codebase_indexer = __esm({
69972
70367
  if (!child) {
69973
70368
  child = {
69974
70369
  name: part,
69975
- path: join72(current.path, part),
70370
+ path: join73(current.path, part),
69976
70371
  type: "directory",
69977
70372
  children: []
69978
70373
  };
@@ -70055,13 +70450,13 @@ __export(index_repo_exports, {
70055
70450
  indexRepoCommand: () => indexRepoCommand
70056
70451
  });
70057
70452
  import { resolve as resolve34 } from "node:path";
70058
- import { existsSync as existsSync55, statSync as statSync16 } from "node:fs";
70453
+ import { existsSync as existsSync56, statSync as statSync16 } from "node:fs";
70059
70454
  import { cwd as cwd2 } from "node:process";
70060
70455
  async function indexRepoCommand(opts, _config) {
70061
70456
  const repoRoot = resolve34(opts.repoPath ?? cwd2());
70062
70457
  printHeader("Index Repository");
70063
70458
  printInfo(`Indexing: ${repoRoot}`);
70064
- if (!existsSync55(repoRoot)) {
70459
+ if (!existsSync56(repoRoot)) {
70065
70460
  printError(`Path does not exist: ${repoRoot}`);
70066
70461
  process.exit(1);
70067
70462
  }
@@ -70313,8 +70708,8 @@ var config_exports2 = {};
70313
70708
  __export(config_exports2, {
70314
70709
  configCommand: () => configCommand
70315
70710
  });
70316
- import { join as join73, resolve as resolve35 } from "node:path";
70317
- import { homedir as homedir19 } from "node:os";
70711
+ import { join as join74, resolve as resolve35 } from "node:path";
70712
+ import { homedir as homedir20 } from "node:os";
70318
70713
  import { cwd as cwd3 } from "node:process";
70319
70714
  function redactIfSensitive(key, value) {
70320
70715
  if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
@@ -70396,7 +70791,7 @@ function handleShow(opts, config) {
70396
70791
  }
70397
70792
  }
70398
70793
  printSection("Config File");
70399
- printInfo(`~/.open-agents/config.json (${join73(homedir19(), ".open-agents", "config.json")})`);
70794
+ printInfo(`~/.open-agents/config.json (${join74(homedir20(), ".open-agents", "config.json")})`);
70400
70795
  printSection("Priority Chain");
70401
70796
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
70402
70797
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -70435,7 +70830,7 @@ function handleSet(opts, _config) {
70435
70830
  const coerced = coerceForSettings(key, value);
70436
70831
  saveProjectSettings(repoRoot, { [key]: coerced });
70437
70832
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
70438
- printInfo(`Saved to ${join73(repoRoot, ".oa", "settings.json")}`);
70833
+ printInfo(`Saved to ${join74(repoRoot, ".oa", "settings.json")}`);
70439
70834
  printInfo("This override applies only when running in this workspace.");
70440
70835
  } catch (err) {
70441
70836
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -70578,8 +70973,8 @@ __export(eval_exports, {
70578
70973
  evalCommand: () => evalCommand
70579
70974
  });
70580
70975
  import { tmpdir as tmpdir10 } from "node:os";
70581
- import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync28 } from "node:fs";
70582
- import { join as join74 } from "node:path";
70976
+ import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync29 } from "node:fs";
70977
+ import { join as join75 } from "node:path";
70583
70978
  async function evalCommand(opts, config) {
70584
70979
  const suiteName = opts.suite ?? "basic";
70585
70980
  const suite = SUITES[suiteName];
@@ -70704,9 +71099,9 @@ async function evalCommand(opts, config) {
70704
71099
  process.exit(failed > 0 ? 1 : 0);
70705
71100
  }
70706
71101
  function createTempEvalRepo() {
70707
- const dir = join74(tmpdir10(), `open-agents-eval-${Date.now()}`);
70708
- mkdirSync29(dir, { recursive: true });
70709
- writeFileSync28(join74(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
71102
+ const dir = join75(tmpdir10(), `open-agents-eval-${Date.now()}`);
71103
+ mkdirSync30(dir, { recursive: true });
71104
+ writeFileSync29(join75(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
70710
71105
  return dir;
70711
71106
  }
70712
71107
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -70766,7 +71161,7 @@ init_updater();
70766
71161
  import { parseArgs as nodeParseArgs2 } from "node:util";
70767
71162
  import { createRequire as createRequire5 } from "node:module";
70768
71163
  import { fileURLToPath as fileURLToPath14 } from "node:url";
70769
- import { dirname as dirname22, join as join75 } from "node:path";
71164
+ import { dirname as dirname22, join as join76 } from "node:path";
70770
71165
 
70771
71166
  // packages/cli/dist/cli.js
70772
71167
  import { createInterface } from "node:readline";
@@ -70873,7 +71268,7 @@ init_output();
70873
71268
  function getVersion5() {
70874
71269
  try {
70875
71270
  const require2 = createRequire5(import.meta.url);
70876
- const pkgPath = join75(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
71271
+ const pkgPath = join76(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
70877
71272
  const pkg = require2(pkgPath);
70878
71273
  return pkg.version;
70879
71274
  } catch {
@@ -71148,12 +71543,12 @@ function crashLog(label, err) {
71148
71543
  const logLine = `[${timestamp}] ${label}: ${msg}
71149
71544
  `;
71150
71545
  try {
71151
- const { appendFileSync: appendFileSync5, mkdirSync: mkdirSync30 } = __require("node:fs");
71152
- const { join: join76 } = __require("node:path");
71153
- const { homedir: homedir20 } = __require("node:os");
71154
- const logDir = join76(homedir20(), ".open-agents");
71155
- mkdirSync30(logDir, { recursive: true });
71156
- appendFileSync5(join76(logDir, "crash.log"), logLine);
71546
+ const { appendFileSync: appendFileSync5, mkdirSync: mkdirSync31 } = __require("node:fs");
71547
+ const { join: join77 } = __require("node:path");
71548
+ const { homedir: homedir21 } = __require("node:os");
71549
+ const logDir = join77(homedir21(), ".open-agents");
71550
+ mkdirSync31(logDir, { recursive: true });
71551
+ appendFileSync5(join77(logDir, "crash.log"), logLine);
71157
71552
  } catch {
71158
71553
  }
71159
71554
  try {