open-agents-ai 0.185.23 → 0.185.26

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 +1661 -721
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11914,8 +11914,8 @@ async function loadTranscribeCli() {
11914
11914
  const nvmBase = join19(homedir7(), ".nvm", "versions", "node");
11915
11915
  if (existsSync16(nvmBase)) {
11916
11916
  try {
11917
- const { readdirSync: readdirSync23 } = await import("node:fs");
11918
- for (const ver of readdirSync23(nvmBase)) {
11917
+ const { readdirSync: readdirSync24 } = await import("node:fs");
11918
+ for (const ver of readdirSync24(nvmBase)) {
11919
11919
  const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
11920
11920
  if (existsSync16(join19(tcPath, "dist", "index.js"))) {
11921
11921
  const { createRequire: createRequire6 } = await import("node:module");
@@ -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");
13964
- const files = readdirSync23(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
13963
+ const { readdirSync: readdirSync24, readFileSync: readFileSync45 } = await import("node:fs");
13964
+ const files = readdirSync24(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
  }
@@ -30460,8 +30460,8 @@ var init_listen = __esm({
30460
30460
  const nvmBase = join48(homedir11(), ".nvm", "versions", "node");
30461
30461
  if (existsSync32(nvmBase)) {
30462
30462
  try {
30463
- const { readdirSync: readdirSync23 } = await import("node:fs");
30464
- for (const ver of readdirSync23(nvmBase)) {
30463
+ const { readdirSync: readdirSync24 } = await import("node:fs");
30464
+ for (const ver of readdirSync24(nvmBase)) {
30465
30465
  const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
30466
30466
  if (existsSync32(join48(tcPath, "dist", "index.js"))) {
30467
30467
  const { createRequire: createRequire6 } = await import("node:module");
@@ -35595,6 +35595,351 @@ connect();
35595
35595
  </body>
35596
35596
  </html>`;
35597
35597
  }
35598
+ function generatePersonaPlexHTML(ppWsUrl, textPrompt, voicePrompt) {
35599
+ return `<!DOCTYPE html>
35600
+ <html lang="en">
35601
+ <head>
35602
+ <meta charset="UTF-8">
35603
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
35604
+ <title>OA \u2014 PersonaPlex Voice</title>
35605
+ <style>
35606
+ * { margin: 0; padding: 0; box-sizing: border-box; }
35607
+ body {
35608
+ background: #1a1a1e;
35609
+ color: #b0b0b0;
35610
+ font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
35611
+ display: flex;
35612
+ flex-direction: column;
35613
+ min-height: 100vh;
35614
+ }
35615
+ #header {
35616
+ background: #1e1e22;
35617
+ padding: 8px 16px;
35618
+ display: flex;
35619
+ align-items: center;
35620
+ gap: 12px;
35621
+ border-bottom: 1px solid #2a2a30;
35622
+ }
35623
+ #header .accent { color: #b2920a; font-weight: bold; font-size: 0.8rem; }
35624
+ #header .badge { font-size: 0.6rem; color: #555; background: #2a2a30; padding: 2px 6px; border-radius: 2px; }
35625
+ #header .status { font-size: 0.7rem; color: #555; }
35626
+ #header .status.live { color: #b2920a; }
35627
+ #waveform {
35628
+ height: 48px;
35629
+ display: flex;
35630
+ align-items: center;
35631
+ justify-content: center;
35632
+ font-size: 1.6rem;
35633
+ line-height: 1;
35634
+ letter-spacing: 0.04em;
35635
+ white-space: nowrap;
35636
+ overflow: hidden;
35637
+ user-select: none;
35638
+ background: #1e1e22;
35639
+ border-bottom: 1px solid #2a2a30;
35640
+ }
35641
+ #conversation {
35642
+ flex: 1;
35643
+ overflow-y: auto;
35644
+ padding: 12px 16px;
35645
+ }
35646
+ .msg {
35647
+ padding: 6px 0;
35648
+ font-size: 0.82rem;
35649
+ line-height: 1.4;
35650
+ }
35651
+ .msg.user { color: #888; }
35652
+ .msg.user::before { content: '\\25B8 '; color: #555; }
35653
+ .msg.agent { color: #b2920a; }
35654
+ .msg.agent::before { content: '\\25B9 '; color: #b2920a; }
35655
+ #footer {
35656
+ background: #1e1e22;
35657
+ padding: 8px 16px;
35658
+ display: flex;
35659
+ align-items: center;
35660
+ gap: 10px;
35661
+ border-top: 1px solid #2a2a30;
35662
+ }
35663
+ button {
35664
+ background: #2a2a30;
35665
+ border: 1px solid #3a3a42;
35666
+ color: #b2920a;
35667
+ padding: 6px 16px;
35668
+ border-radius: 3px;
35669
+ font-family: inherit;
35670
+ font-size: 0.75rem;
35671
+ cursor: pointer;
35672
+ transition: background 0.15s;
35673
+ }
35674
+ button:hover { background: #3a3a42; }
35675
+ button.active { background: #3a2a10; border-color: #b2920a; }
35676
+ #footer .hint { font-size: 0.65rem; color: #444; }
35677
+ </style>
35678
+ </head>
35679
+ <body>
35680
+ <div id="header">
35681
+ <span class="accent">OA</span>
35682
+ <span class="badge">PersonaPlex 7B</span>
35683
+ <span id="status" class="status">connecting</span>
35684
+ </div>
35685
+ <div id="waveform"></div>
35686
+ <div id="conversation"></div>
35687
+ <div id="footer">
35688
+ <button id="micBtn" onclick="toggleMic()">mic</button>
35689
+ <span class="hint" id="hint">tap to start full-duplex voice</span>
35690
+ </div>
35691
+
35692
+ <script>
35693
+ const waveEl = document.getElementById('waveform');
35694
+ const statusEl = document.getElementById('status');
35695
+ const convoEl = document.getElementById('conversation');
35696
+ const micBtn = document.getElementById('micBtn');
35697
+ const hintEl = document.getElementById('hint');
35698
+
35699
+ // PersonaPlex WebSocket URL (moshi.server)
35700
+ const PP_WS_URL = ${JSON.stringify(ppWsUrl)};
35701
+ const TEXT_PROMPT = ${JSON.stringify(textPrompt)};
35702
+ const VOICE_PROMPT = ${JSON.stringify(voicePrompt)};
35703
+
35704
+ // Braille waveform
35705
+ const DENSITY = ['\\u2800','\\u2840','\\u28C0','\\u28C4','\\u28E4','\\u28E6','\\u28F6','\\u28F7','\\u28FF'];
35706
+ const WAVE = [...DENSITY, ...DENSITY.slice(1,-1).reverse()];
35707
+ const THEME_IDLE = ['#1e1e22','#2a2a30','#333338','#3e3e44','#4a4a52','#555560','#666670','#777780','#888890'];
35708
+ const THEME_SPEAKING = ['#1e1e22','#2a2510','#3a3518','#4a4520','#5a5528','#6a6530','#8a7a20','#a89010','#b2920a'];
35709
+ const THEME_LISTENING = ['#1e1e22','#2a2818','#3a3820','#4a4828','#5a5830','#6a6838','#8a8830','#a8a020','#b2920a'];
35710
+ function buildColorRamp(r) { return [...r, ...r.slice(1,-1).reverse()]; }
35711
+
35712
+ let waveFrame = 0, waveState = 'idle', micLevel = 0;
35713
+ function renderWave() {
35714
+ const cols = Math.min(40, Math.floor(waveEl.offsetWidth / 20)) || 30;
35715
+ const cl = WAVE.length;
35716
+ const theme = waveState==='speaking'?THEME_SPEAKING:waveState==='listening'?THEME_LISTENING:THEME_IDLE;
35717
+ const cr = buildColorRamp(theme);
35718
+ const bp = Math.sin(waveFrame*0.06);
35719
+ const speed = waveState==='speaking'?2.5+bp*0.5:waveState==='listening'?2.0+micLevel*3.0+bp*0.3:1.2+bp*0.8;
35720
+ const ds = waveState==='idle'?0.35+bp*0.15:waveState==='listening'?0.3+micLevel*0.7:0.6+bp*0.2;
35721
+ const sa = 1.5+ds*2.0;
35722
+ let html='';
35723
+ for(let c=0;c<cols;c++){
35724
+ const so=Math.sin(c*0.1+waveFrame*0.02)*sa;
35725
+ const rp=c*speed+waveFrame+so;
35726
+ const np=((rp%cl)+cl)%cl;
35727
+ let wi=Math.round(np)%cl;
35728
+ let amp=wi<=8?wi:16-wi;
35729
+ const sc=Math.round(amp*ds);
35730
+ let si=wi<=8?sc:16-sc;
35731
+ si=Math.max(0,Math.min(cl-1,si));
35732
+ html+='<span style="color:'+cr[si]+'">'+WAVE[si]+'</span>';
35733
+ }
35734
+ waveEl.innerHTML=html;
35735
+ }
35736
+ setInterval(()=>{waveFrame++;renderWave();},80);
35737
+
35738
+ // \u2500\u2500 PersonaPlex connection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35739
+ let ppWs = null;
35740
+ let micCtx = null, micStream = null, micActive = false;
35741
+ let playbackCtx = null;
35742
+ let handshakeReceived = false;
35743
+ let opusEncoder = null, opusDecoder = null;
35744
+ let agentText = '';
35745
+
35746
+ function connectPP() {
35747
+ const url = PP_WS_URL + '/api/chat?text_prompt=' + encodeURIComponent(TEXT_PROMPT) +
35748
+ '&voice_prompt=' + encodeURIComponent(VOICE_PROMPT) + '&seed=-1';
35749
+ statusEl.textContent = 'connecting to PersonaPlex...';
35750
+ ppWs = new WebSocket(url);
35751
+ ppWs.binaryType = 'arraybuffer';
35752
+
35753
+ ppWs.onopen = () => {
35754
+ statusEl.textContent = 'loading persona...';
35755
+ statusEl.className = 'status';
35756
+ };
35757
+
35758
+ ppWs.onmessage = (evt) => {
35759
+ if (!(evt.data instanceof ArrayBuffer)) return;
35760
+ const bytes = new Uint8Array(evt.data);
35761
+ if (bytes.length === 0) return;
35762
+
35763
+ const kind = bytes[0];
35764
+ if (kind === 0x00) {
35765
+ // Handshake \u2014 server is ready
35766
+ handshakeReceived = true;
35767
+ statusEl.textContent = 'ready \u2014 full duplex';
35768
+ statusEl.className = 'status live';
35769
+ hintEl.textContent = 'tap mic to start talking';
35770
+ } else if (kind === 0x01) {
35771
+ // Audio (Opus) from PersonaPlex
35772
+ const opusData = bytes.slice(1);
35773
+ playOpus(opusData);
35774
+ waveState = 'speaking';
35775
+ } else if (kind === 0x02) {
35776
+ // Text token from PersonaPlex
35777
+ const text = new TextDecoder().decode(bytes.slice(1));
35778
+ agentText += text;
35779
+ // Flush on sentence boundary
35780
+ if (/[.!?]\\s*$/.test(agentText) || agentText.length > 200) {
35781
+ addTranscript('agent', agentText.trim());
35782
+ agentText = '';
35783
+ }
35784
+ }
35785
+ };
35786
+
35787
+ ppWs.onclose = () => {
35788
+ handshakeReceived = false;
35789
+ statusEl.textContent = 'disconnected';
35790
+ statusEl.className = 'status';
35791
+ if (agentText.trim()) { addTranscript('agent', agentText.trim()); agentText=''; }
35792
+ setTimeout(connectPP, 3000);
35793
+ };
35794
+
35795
+ ppWs.onerror = () => {};
35796
+ }
35797
+
35798
+ function addTranscript(speaker, text) {
35799
+ const div = document.createElement('div');
35800
+ div.className = 'msg ' + speaker;
35801
+ div.textContent = text;
35802
+ convoEl.appendChild(div);
35803
+ convoEl.scrollTop = convoEl.scrollHeight;
35804
+ }
35805
+
35806
+ // \u2500\u2500 Opus playback via WebAudio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35807
+ // PersonaPlex sends Opus-encoded audio via sphn. We decode via AudioDecoder or fallback.
35808
+
35809
+ async function playOpus(opusData) {
35810
+ // Use raw PCM fallback \u2014 decode Opus in a worker or use AudioContext.decodeAudioData
35811
+ // For simplicity, we'll use the AudioDecoder API if available
35812
+ if (!playbackCtx) playbackCtx = new AudioContext({ sampleRate: 24000 });
35813
+
35814
+ try {
35815
+ // Wrap opus in a minimal ogg-like container isn't practical,
35816
+ // so we attempt raw decode via AudioDecoder (Chrome 94+)
35817
+ if (typeof AudioDecoder !== 'undefined' && !opusDecoder) {
35818
+ opusDecoder = new AudioDecoder({
35819
+ output: (frame) => {
35820
+ const buf = playbackCtx.createBuffer(1, frame.numberOfFrames, frame.sampleRate);
35821
+ frame.copyTo(buf.getChannelData(0), { planeIndex: 0 });
35822
+ const src = playbackCtx.createBufferSource();
35823
+ src.buffer = buf;
35824
+ src.connect(playbackCtx.destination);
35825
+ src.start();
35826
+ frame.close();
35827
+ },
35828
+ error: (e) => { console.warn('opus decode err:', e); }
35829
+ });
35830
+ opusDecoder.configure({
35831
+ codec: 'opus',
35832
+ sampleRate: 24000,
35833
+ numberOfChannels: 1,
35834
+ });
35835
+ }
35836
+ if (opusDecoder && opusDecoder.state === 'configured') {
35837
+ opusDecoder.decode(new EncodedAudioChunk({
35838
+ type: 'key',
35839
+ timestamp: 0,
35840
+ data: opusData,
35841
+ }));
35842
+ }
35843
+ } catch (e) {
35844
+ // Fallback: skip frame
35845
+ console.warn('Opus playback unavailable:', e);
35846
+ }
35847
+ }
35848
+
35849
+ // \u2500\u2500 Microphone \u2192 Opus \u2192 PersonaPlex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35850
+
35851
+ let scriptProcessor = null;
35852
+
35853
+ async function toggleMic() {
35854
+ if (micActive) { stopMic(); return; }
35855
+ if (!handshakeReceived) {
35856
+ hintEl.textContent = 'waiting for PersonaPlex...';
35857
+ return;
35858
+ }
35859
+ try {
35860
+ if (!micCtx) micCtx = new AudioContext({ sampleRate: 24000 });
35861
+ micStream = await navigator.mediaDevices.getUserMedia({
35862
+ audio: { sampleRate: 24000, channelCount: 1, echoCancellation: true, noiseSuppression: true }
35863
+ });
35864
+ const source = micCtx.createMediaStreamSource(micStream);
35865
+ scriptProcessor = micCtx.createScriptProcessor(1920, 1, 1); // 80ms at 24kHz
35866
+
35867
+ // Use AudioEncoder to send Opus to PersonaPlex
35868
+ let audioEncoder = null;
35869
+ if (typeof AudioEncoder !== 'undefined') {
35870
+ audioEncoder = new AudioEncoder({
35871
+ output: (chunk) => {
35872
+ if (!ppWs || ppWs.readyState !== 1) return;
35873
+ const buf = new ArrayBuffer(chunk.byteLength + 1);
35874
+ const view = new Uint8Array(buf);
35875
+ view[0] = 0x01; // audio kind byte
35876
+ chunk.copyTo(view.subarray(1));
35877
+ ppWs.send(buf);
35878
+ },
35879
+ error: (e) => { console.warn('encode err:', e); }
35880
+ });
35881
+ audioEncoder.configure({
35882
+ codec: 'opus',
35883
+ sampleRate: 24000,
35884
+ numberOfChannels: 1,
35885
+ bitrate: 24000,
35886
+ });
35887
+ }
35888
+
35889
+ let frameCounter = 0;
35890
+ scriptProcessor.onaudioprocess = (e) => {
35891
+ if (!micActive || !ppWs || ppWs.readyState !== 1) return;
35892
+ const input = e.inputBuffer.getChannelData(0);
35893
+ micLevel = Math.min(1, rms(input) * 5);
35894
+
35895
+ if (audioEncoder && audioEncoder.state === 'configured') {
35896
+ const data = new AudioData({
35897
+ format: 'f32',
35898
+ sampleRate: 24000,
35899
+ numberOfFrames: input.length,
35900
+ numberOfChannels: 1,
35901
+ timestamp: frameCounter * (input.length / 24000) * 1e6,
35902
+ data: input,
35903
+ });
35904
+ audioEncoder.encode(data);
35905
+ data.close();
35906
+ frameCounter++;
35907
+ }
35908
+ };
35909
+ source.connect(scriptProcessor);
35910
+ scriptProcessor.connect(micCtx.destination);
35911
+ micActive = true;
35912
+ waveState = 'listening';
35913
+ micBtn.textContent = 'stop';
35914
+ micBtn.classList.add('active');
35915
+ hintEl.textContent = 'full-duplex active \u2014 speak freely';
35916
+ } catch (err) {
35917
+ hintEl.textContent = 'mic error: ' + err.message;
35918
+ }
35919
+ }
35920
+
35921
+ function stopMic() {
35922
+ micActive = false;
35923
+ micLevel = 0;
35924
+ waveState = 'idle';
35925
+ if (scriptProcessor) { scriptProcessor.disconnect(); scriptProcessor = null; }
35926
+ if (micStream) { micStream.getTracks().forEach(t => t.stop()); micStream = null; }
35927
+ micBtn.textContent = 'mic';
35928
+ micBtn.classList.remove('active');
35929
+ hintEl.textContent = 'tap mic to start talking';
35930
+ }
35931
+
35932
+ function rms(arr) {
35933
+ let sum = 0;
35934
+ for (let i = 0; i < arr.length; i++) sum += arr[i] * arr[i];
35935
+ return Math.sqrt(sum / arr.length);
35936
+ }
35937
+
35938
+ connectPP();
35939
+ </script>
35940
+ </body>
35941
+ </html>`;
35942
+ }
35598
35943
  function renderVoiceSessionStart(tunnelUrl) {
35599
35944
  process.stdout.write(`
35600
35945
  ${c2.cyan("\u2601")} ${c2.bold("Live Voice Session")}
@@ -35641,6 +35986,10 @@ var init_voice_session = __esm({
35641
35986
  runtimeTimer = null;
35642
35987
  idleTimer = null;
35643
35988
  ttsSpeaking = false;
35989
+ /** When set, serve PersonaPlex frontend that connects directly to this moshi.server WS URL */
35990
+ personaPlexWsUrl = null;
35991
+ personaPlexTextPrompt = "You enjoy having a good conversation.";
35992
+ personaPlexVoicePrompt = "NATF2.pt";
35644
35993
  /** Idle timeout before auto-closing (ms). Default 60s — no users connected → session ends. */
35645
35994
  idleTimeoutMs = 6e4;
35646
35995
  /** Callback invoked when user audio chunk arrives (PCM 16kHz 16-bit mono) */
@@ -35829,7 +36178,11 @@ var init_voice_session = __esm({
35829
36178
  handleHTTP(req, res) {
35830
36179
  if (req.url === "/" || req.url === "/index.html") {
35831
36180
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
35832
- res.end(generateFrontendHTML());
36181
+ if (this.personaPlexWsUrl) {
36182
+ res.end(generatePersonaPlexHTML(this.personaPlexWsUrl, this.personaPlexTextPrompt, this.personaPlexVoicePrompt));
36183
+ } else {
36184
+ res.end(generateFrontendHTML());
36185
+ }
35833
36186
  } else if (req.url === "/health") {
35834
36187
  res.writeHead(200, { "Content-Type": "application/json" });
35835
36188
  res.end(JSON.stringify({
@@ -38906,26 +39259,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
38906
39259
  async function fetchPeerModels(peerId, authKey) {
38907
39260
  try {
38908
39261
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
38909
- const { existsSync: existsSync56, readFileSync: readFileSync44 } = await import("node:fs");
38910
- const { join: join76 } = await import("node:path");
39262
+ const { existsSync: existsSync57, readFileSync: readFileSync45 } = await import("node:fs");
39263
+ const { join: join77 } = await import("node:path");
38911
39264
  const cwd4 = process.cwd();
38912
39265
  const nexusTool = new NexusTool2(cwd4);
38913
39266
  const nexusDir = nexusTool.getNexusDir();
38914
39267
  let isLocalPeer = false;
38915
39268
  try {
38916
- const statusPath = join76(nexusDir, "status.json");
38917
- if (existsSync56(statusPath)) {
38918
- const status = JSON.parse(readFileSync44(statusPath, "utf8"));
39269
+ const statusPath = join77(nexusDir, "status.json");
39270
+ if (existsSync57(statusPath)) {
39271
+ const status = JSON.parse(readFileSync45(statusPath, "utf8"));
38919
39272
  if (status.peerId === peerId)
38920
39273
  isLocalPeer = true;
38921
39274
  }
38922
39275
  } catch {
38923
39276
  }
38924
39277
  if (isLocalPeer) {
38925
- const pricingPath = join76(nexusDir, "pricing.json");
38926
- if (existsSync56(pricingPath)) {
39278
+ const pricingPath = join77(nexusDir, "pricing.json");
39279
+ if (existsSync57(pricingPath)) {
38927
39280
  try {
38928
- const pricing = JSON.parse(readFileSync44(pricingPath, "utf8"));
39281
+ const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
38929
39282
  const localModels = (pricing.models || []).map((m) => ({
38930
39283
  name: m.model || "unknown",
38931
39284
  size: m.parameterSize || "",
@@ -38939,10 +39292,10 @@ async function fetchPeerModels(peerId, authKey) {
38939
39292
  }
38940
39293
  }
38941
39294
  }
38942
- const cachePath = join76(nexusDir, "peer-models-cache.json");
38943
- if (existsSync56(cachePath)) {
39295
+ const cachePath = join77(nexusDir, "peer-models-cache.json");
39296
+ if (existsSync57(cachePath)) {
38944
39297
  try {
38945
- const cache4 = JSON.parse(readFileSync44(cachePath, "utf8"));
39298
+ const cache4 = JSON.parse(readFileSync45(cachePath, "utf8"));
38946
39299
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
38947
39300
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
38948
39301
  if (age < 5 * 60 * 1e3) {
@@ -39057,10 +39410,10 @@ async function fetchPeerModels(peerId, authKey) {
39057
39410
  } catch {
39058
39411
  }
39059
39412
  if (isLocalPeer) {
39060
- const pricingPath = join76(nexusDir, "pricing.json");
39061
- if (existsSync56(pricingPath)) {
39413
+ const pricingPath = join77(nexusDir, "pricing.json");
39414
+ if (existsSync57(pricingPath)) {
39062
39415
  try {
39063
- const pricing = JSON.parse(readFileSync44(pricingPath, "utf8"));
39416
+ const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
39064
39417
  return (pricing.models || []).map((m) => ({
39065
39418
  name: m.model || "unknown",
39066
39419
  size: m.parameterSize || "",
@@ -40724,13 +41077,505 @@ var init_tui_select = __esm({
40724
41077
  }
40725
41078
  });
40726
41079
 
41080
+ // packages/cli/dist/tui/personaplex.js
41081
+ var personaplex_exports = {};
41082
+ __export(personaplex_exports, {
41083
+ autoSetupPersonaPlex: () => autoSetupPersonaPlex,
41084
+ clonePersonaPlexVoice: () => clonePersonaPlexVoice,
41085
+ detectPersonaPlexCapability: () => detectPersonaPlexCapability,
41086
+ getPersonaPlexWSUrl: () => getPersonaPlexWSUrl,
41087
+ installPersonaPlex: () => installPersonaPlex,
41088
+ isPersonaPlexInstalled: () => isPersonaPlexInstalled,
41089
+ isPersonaPlexRunning: () => isPersonaPlexRunning,
41090
+ listPersonaPlexVoices: () => listPersonaPlexVoices,
41091
+ patchFrontendVoiceList: () => patchFrontendVoiceList,
41092
+ provisionShippedVoices: () => provisionShippedVoices,
41093
+ startPersonaPlexDaemon: () => startPersonaPlexDaemon,
41094
+ stopPersonaPlex: () => stopPersonaPlex
41095
+ });
41096
+ import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, mkdirSync as mkdirSync15, copyFileSync as copyFileSync2, readdirSync as readdirSync11 } from "node:fs";
41097
+ import { join as join54, dirname as dirname18 } from "node:path";
41098
+ import { homedir as homedir13 } from "node:os";
41099
+ import { execSync as execSync27, spawn as spawn19 } from "node:child_process";
41100
+ import { fileURLToPath as fileURLToPath11 } from "node:url";
41101
+ function detectPersonaPlexCapability() {
41102
+ try {
41103
+ const nvsmi = execSync27("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
41104
+ encoding: "utf8",
41105
+ timeout: 5e3,
41106
+ stdio: "pipe"
41107
+ }).trim();
41108
+ if (!nvsmi) {
41109
+ return { supported: false, reason: "No NVIDIA GPU detected", gpuName: "", vramGB: 0 };
41110
+ }
41111
+ const [gpuName, vramMB] = nvsmi.split("\n")[0].split(", ");
41112
+ const vramGB = parseInt(vramMB ?? "0", 10) / 1024;
41113
+ if (vramGB < 16) {
41114
+ return { supported: false, reason: `GPU has ${vramGB.toFixed(1)}GB VRAM (need \u226516GB)`, gpuName: gpuName ?? "", vramGB };
41115
+ }
41116
+ try {
41117
+ execSync27('python3 -c "import torch; assert torch.cuda.is_available()"', {
41118
+ timeout: 1e4,
41119
+ stdio: "pipe"
41120
+ });
41121
+ } catch {
41122
+ return { supported: false, reason: "PyTorch CUDA not available", gpuName: gpuName ?? "", vramGB };
41123
+ }
41124
+ return { supported: true, reason: "OK", gpuName: gpuName ?? "", vramGB };
41125
+ } catch {
41126
+ return { supported: false, reason: "nvidia-smi not found", gpuName: "", vramGB: 0 };
41127
+ }
41128
+ }
41129
+ function isPersonaPlexRunning() {
41130
+ if (!existsSync37(PID_FILE))
41131
+ return false;
41132
+ const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
41133
+ if (isNaN(pid) || pid <= 0)
41134
+ return false;
41135
+ try {
41136
+ process.kill(pid, 0);
41137
+ return true;
41138
+ } catch {
41139
+ return false;
41140
+ }
41141
+ }
41142
+ function getPersonaPlexWSUrl() {
41143
+ if (!isPersonaPlexRunning())
41144
+ return null;
41145
+ if (!existsSync37(PORT_FILE))
41146
+ return null;
41147
+ const port = parseInt(readFileSync28(PORT_FILE, "utf8").trim(), 10);
41148
+ return isNaN(port) ? null : `wss://127.0.0.1:${port}`;
41149
+ }
41150
+ function isPersonaPlexInstalled() {
41151
+ return existsSync37(join54(PERSONAPLEX_DIR, "model_ready"));
41152
+ }
41153
+ async function installPersonaPlex(onInfo) {
41154
+ const log = onInfo ?? (() => {
41155
+ });
41156
+ mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
41157
+ const venvDir = join54(PERSONAPLEX_DIR, "venv");
41158
+ if (!existsSync37(venvDir)) {
41159
+ log("Creating Python virtual environment...");
41160
+ try {
41161
+ execSync27(`python3 -m venv "${venvDir}"`, { timeout: 6e4, stdio: "pipe" });
41162
+ } catch (err) {
41163
+ log(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
41164
+ return false;
41165
+ }
41166
+ }
41167
+ const pip = process.platform === "win32" ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
41168
+ const python = process.platform === "win32" ? join54(venvDir, "Scripts", "python.exe") : join54(venvDir, "bin", "python3");
41169
+ log("Checking system dependencies (libopus)...");
41170
+ try {
41171
+ if (process.platform === "linux") {
41172
+ execSync27("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
41173
+ } else if (process.platform === "darwin") {
41174
+ execSync27("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
41175
+ }
41176
+ } catch {
41177
+ }
41178
+ log("Installing PersonaPlex (moshi package)...");
41179
+ const repoDir = join54(PERSONAPLEX_DIR, "personaplex-repo");
41180
+ try {
41181
+ if (!existsSync37(repoDir)) {
41182
+ execSync27(`git clone https://github.com/NVIDIA/personaplex.git "${repoDir}"`, { timeout: 12e4, stdio: "pipe" });
41183
+ }
41184
+ execSync27(`"${pip}" install --quiet "${join54(repoDir, "moshi")}/."`, { timeout: 3e5, stdio: "pipe" });
41185
+ } catch (err) {
41186
+ log(`Moshi install failed: ${err instanceof Error ? err.message : String(err)}`);
41187
+ try {
41188
+ execSync27(`"${pip}" install --quiet torch torchaudio websockets soundfile huggingface_hub`, { timeout: 3e5, stdio: "pipe" });
41189
+ } catch {
41190
+ }
41191
+ return false;
41192
+ }
41193
+ const serverPy = join54(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
41194
+ try {
41195
+ const sitePackages = execSync27(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41196
+ encoding: "utf8",
41197
+ timeout: 5e3,
41198
+ stdio: "pipe"
41199
+ }).trim();
41200
+ const serverFile = join54(sitePackages, "server.py");
41201
+ if (existsSync37(serverFile)) {
41202
+ let src = readFileSync28(serverFile, "utf8");
41203
+ if (src.includes('int(request["seed"])')) {
41204
+ src = src.replace('int(request["seed"])', 'int(request.query["seed"])');
41205
+ writeFileSync16(serverFile, src);
41206
+ log("Applied seed parameter bug fix to moshi server.");
41207
+ }
41208
+ }
41209
+ } catch {
41210
+ }
41211
+ log("PersonaPlex installed. Model will download on first launch (~14GB).");
41212
+ writeFileSync16(join54(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
41213
+ log("PersonaPlex installed successfully.");
41214
+ return true;
41215
+ }
41216
+ async function startPersonaPlexDaemon(onInfo) {
41217
+ const log = onInfo ?? (() => {
41218
+ });
41219
+ const PORT = 8998;
41220
+ if (isPersonaPlexRunning()) {
41221
+ const url = getPersonaPlexWSUrl();
41222
+ if (url) {
41223
+ log(`PersonaPlex already running at ${url}`);
41224
+ return url;
41225
+ }
41226
+ }
41227
+ if (!isPersonaPlexInstalled()) {
41228
+ log("PersonaPlex not installed. Run /voice personaplex to set up.");
41229
+ return null;
41230
+ }
41231
+ mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
41232
+ const venvPython2 = process.platform === "win32" ? join54(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join54(PERSONAPLEX_DIR, "venv", "bin", "python3");
41233
+ const sslDir = join54(PERSONAPLEX_DIR, "ssl");
41234
+ mkdirSync15(sslDir, { recursive: true });
41235
+ log("Starting PersonaPlex daemon (loading ~7B model)...");
41236
+ const child = spawn19(venvPython2, [
41237
+ "-m",
41238
+ "moshi.server",
41239
+ "--host",
41240
+ "0.0.0.0",
41241
+ "--port",
41242
+ String(PORT),
41243
+ "--ssl",
41244
+ sslDir,
41245
+ "--device",
41246
+ "cuda"
41247
+ ], {
41248
+ stdio: ["ignore", "pipe", "pipe"],
41249
+ detached: true,
41250
+ env: { ...process.env },
41251
+ cwd: PERSONAPLEX_DIR
41252
+ });
41253
+ if (child.pid) {
41254
+ writeFileSync16(PID_FILE, String(child.pid));
41255
+ writeFileSync16(PORT_FILE, String(PORT));
41256
+ }
41257
+ child.unref();
41258
+ const { createWriteStream } = await import("node:fs");
41259
+ const logStream = createWriteStream(LOG_FILE, { flags: "w" });
41260
+ child.stdout?.pipe(logStream);
41261
+ child.stderr?.pipe(logStream);
41262
+ const startTime = Date.now();
41263
+ const timeout = 12e4;
41264
+ while (Date.now() - startTime < timeout) {
41265
+ try {
41266
+ if (child.pid)
41267
+ process.kill(child.pid, 0);
41268
+ } catch {
41269
+ log("PersonaPlex daemon exited unexpectedly. Check daemon.log.");
41270
+ return null;
41271
+ }
41272
+ try {
41273
+ execSync27(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
41274
+ timeout: 3e3,
41275
+ stdio: "pipe",
41276
+ encoding: "utf8"
41277
+ });
41278
+ const url = `wss://127.0.0.1:${PORT}`;
41279
+ log(`PersonaPlex ready at ${url}`);
41280
+ return url;
41281
+ } catch {
41282
+ }
41283
+ await new Promise((r) => setTimeout(r, 2e3));
41284
+ const elapsed = Math.round((Date.now() - startTime) / 1e3);
41285
+ if (elapsed % 10 === 0)
41286
+ log(`Still loading... (${elapsed}s)`);
41287
+ }
41288
+ log("PersonaPlex daemon failed to start within 120s. Check daemon.log.");
41289
+ return null;
41290
+ }
41291
+ function stopPersonaPlex() {
41292
+ if (!existsSync37(PID_FILE))
41293
+ return;
41294
+ const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
41295
+ if (isNaN(pid) || pid <= 0)
41296
+ return;
41297
+ try {
41298
+ if (process.platform === "win32") {
41299
+ execSync27(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
41300
+ } else {
41301
+ process.kill(pid, "SIGTERM");
41302
+ }
41303
+ } catch {
41304
+ }
41305
+ }
41306
+ function listPersonaPlexVoices() {
41307
+ const voices = [];
41308
+ const builtins = [
41309
+ "NATF0",
41310
+ "NATF1",
41311
+ "NATF2",
41312
+ "NATF3",
41313
+ "NATM0",
41314
+ "NATM1",
41315
+ "NATM2",
41316
+ "NATM3",
41317
+ "VARF0",
41318
+ "VARF1",
41319
+ "VARF2",
41320
+ "VARF3",
41321
+ "VARF4",
41322
+ "VARM0",
41323
+ "VARM1",
41324
+ "VARM2",
41325
+ "VARM3",
41326
+ "VARM4"
41327
+ ];
41328
+ for (const name of builtins) {
41329
+ voices.push({ name, type: "builtin", path: `${name}.pt` });
41330
+ }
41331
+ if (existsSync37(CUSTOM_VOICES_DIR)) {
41332
+ try {
41333
+ const { readdirSync: readdirSync24 } = __require("node:fs");
41334
+ for (const f of readdirSync24(CUSTOM_VOICES_DIR)) {
41335
+ if (f.endsWith(".pt")) {
41336
+ const name = f.replace(/\.pt$/, "");
41337
+ voices.push({ name, type: "custom", path: join54(CUSTOM_VOICES_DIR, f) });
41338
+ }
41339
+ }
41340
+ } catch {
41341
+ }
41342
+ }
41343
+ return voices;
41344
+ }
41345
+ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
41346
+ const log = onInfo ?? (() => {
41347
+ });
41348
+ if (!isPersonaPlexInstalled()) {
41349
+ log("PersonaPlex not installed. Run /voice personaplex first.");
41350
+ return null;
41351
+ }
41352
+ if (!existsSync37(inputWav)) {
41353
+ log(`Input WAV not found: ${inputWav}`);
41354
+ return null;
41355
+ }
41356
+ mkdirSync15(CUSTOM_VOICES_DIR, { recursive: true });
41357
+ const outputPt = join54(CUSTOM_VOICES_DIR, `${voiceName}.pt`);
41358
+ if (existsSync37(outputPt)) {
41359
+ log(`Voice "${voiceName}" already exists. Delete ${outputPt} to re-clone.`);
41360
+ return outputPt;
41361
+ }
41362
+ const venvPython2 = process.platform === "win32" ? join54(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join54(PERSONAPLEX_DIR, "venv", "bin", "python3");
41363
+ const cloneScript = join54(PERSONAPLEX_DIR, "clone-voice.py");
41364
+ if (!existsSync37(cloneScript)) {
41365
+ log("clone-voice.py not found. Reinstall PersonaPlex.");
41366
+ return null;
41367
+ }
41368
+ log(`Cloning voice "${voiceName}" from ${inputWav}...`);
41369
+ log("This requires loading the full 7B model \u2014 may take 30-60s...");
41370
+ return new Promise((resolve36) => {
41371
+ const child = spawn19(venvPython2, [
41372
+ cloneScript,
41373
+ "--input",
41374
+ inputWav,
41375
+ "--name",
41376
+ voiceName,
41377
+ "--device",
41378
+ "cuda"
41379
+ ], {
41380
+ stdio: ["ignore", "pipe", "pipe"],
41381
+ env: { ...process.env },
41382
+ cwd: PERSONAPLEX_DIR
41383
+ });
41384
+ let output = "";
41385
+ child.stdout?.on("data", (d) => {
41386
+ const line = d.toString();
41387
+ output += line;
41388
+ for (const l of line.split("\n").filter((s) => s.trim())) {
41389
+ log(l.trim());
41390
+ }
41391
+ });
41392
+ child.stderr?.on("data", (d) => {
41393
+ output += d.toString();
41394
+ });
41395
+ child.on("close", (code) => {
41396
+ if (code === 0 && existsSync37(outputPt)) {
41397
+ log(`Voice "${voiceName}" cloned successfully.`);
41398
+ resolve36(outputPt);
41399
+ } else {
41400
+ log(`Voice cloning failed (exit ${code}).`);
41401
+ resolve36(null);
41402
+ }
41403
+ });
41404
+ });
41405
+ }
41406
+ function getShippedVoicesDir() {
41407
+ const candidates = [
41408
+ join54(PERSONAPLEX_DIR, "shipped_voices"),
41409
+ // cached copy
41410
+ join54(process.cwd(), "voices", "personaplex")
41411
+ // repo root
41412
+ ];
41413
+ try {
41414
+ const modDir = dirname18(fileURLToPath11(import.meta.url));
41415
+ candidates.push(join54(modDir, "..", "..", "..", "voices", "personaplex"));
41416
+ candidates.push(join54(modDir, "..", "..", "..", "..", "voices", "personaplex"));
41417
+ } catch {
41418
+ }
41419
+ for (const dir of candidates) {
41420
+ if (existsSync37(dir)) {
41421
+ try {
41422
+ const files = readdirSync11(dir);
41423
+ if (files.some((f) => f.endsWith(".pt")))
41424
+ return dir;
41425
+ } catch {
41426
+ }
41427
+ }
41428
+ }
41429
+ return null;
41430
+ }
41431
+ function provisionShippedVoices(onInfo) {
41432
+ const log = onInfo ?? (() => {
41433
+ });
41434
+ const shippedDir = getShippedVoicesDir();
41435
+ if (!shippedDir)
41436
+ return 0;
41437
+ const hfVoicesDir = getHFVoicesDir();
41438
+ mkdirSync15(CUSTOM_VOICES_DIR, { recursive: true });
41439
+ let deployed = 0;
41440
+ try {
41441
+ for (const f of readdirSync11(shippedDir)) {
41442
+ if (!f.endsWith(".pt"))
41443
+ continue;
41444
+ const customDst = join54(CUSTOM_VOICES_DIR, f);
41445
+ if (!existsSync37(customDst)) {
41446
+ copyFileSync2(join54(shippedDir, f), customDst);
41447
+ }
41448
+ if (hfVoicesDir) {
41449
+ const hfDst = join54(hfVoicesDir, f);
41450
+ if (!existsSync37(hfDst)) {
41451
+ copyFileSync2(join54(shippedDir, f), hfDst);
41452
+ log(`Deployed voice: ${f.replace(".pt", "")}`);
41453
+ deployed++;
41454
+ }
41455
+ }
41456
+ }
41457
+ } catch {
41458
+ }
41459
+ const shippedScript = join54(shippedDir, "clone-voice.py");
41460
+ const targetScript = join54(PERSONAPLEX_DIR, "clone-voice.py");
41461
+ if (existsSync37(shippedScript) && !existsSync37(targetScript)) {
41462
+ try {
41463
+ copyFileSync2(shippedScript, targetScript);
41464
+ } catch {
41465
+ }
41466
+ }
41467
+ return deployed;
41468
+ }
41469
+ function getHFVoicesDir() {
41470
+ const hfBase = join54(homedir13(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
41471
+ if (!existsSync37(hfBase))
41472
+ return null;
41473
+ try {
41474
+ const snapshots = join54(hfBase, "snapshots");
41475
+ if (!existsSync37(snapshots))
41476
+ return null;
41477
+ for (const snap of readdirSync11(snapshots)) {
41478
+ const voicesDir = join54(snapshots, snap, "voices");
41479
+ if (existsSync37(voicesDir))
41480
+ return voicesDir;
41481
+ }
41482
+ } catch {
41483
+ }
41484
+ return null;
41485
+ }
41486
+ function patchFrontendVoiceList(onInfo) {
41487
+ const log = onInfo ?? (() => {
41488
+ });
41489
+ const hfBase = join54(homedir13(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
41490
+ if (!existsSync37(hfBase))
41491
+ return;
41492
+ try {
41493
+ const snapshots = join54(hfBase, "snapshots");
41494
+ for (const snap of readdirSync11(snapshots)) {
41495
+ const distDir = join54(snapshots, snap, "dist", "assets");
41496
+ if (!existsSync37(distDir))
41497
+ continue;
41498
+ for (const f of readdirSync11(distDir)) {
41499
+ if (!f.startsWith("index-") || !f.endsWith(".js"))
41500
+ continue;
41501
+ const jsPath = join54(distDir, f);
41502
+ let js = readFileSync28(jsPath, "utf8");
41503
+ const customVoices = [];
41504
+ if (existsSync37(CUSTOM_VOICES_DIR)) {
41505
+ for (const vf of readdirSync11(CUSTOM_VOICES_DIR)) {
41506
+ if (vf.endsWith(".pt")) {
41507
+ const name = vf.replace(".pt", "");
41508
+ if (!js.includes(`"${vf}"`)) {
41509
+ customVoices.push(vf);
41510
+ }
41511
+ }
41512
+ }
41513
+ }
41514
+ if (customVoices.length === 0)
41515
+ continue;
41516
+ const needle = '"VARM4.pt"]';
41517
+ if (js.includes(needle)) {
41518
+ const additions = customVoices.map((v) => `"${v}"`).join(", ");
41519
+ js = js.replace(needle, `"VARM4.pt", ${additions}]`);
41520
+ writeFileSync16(jsPath, js);
41521
+ log(`Added ${customVoices.length} custom voice(s) to frontend: ${customVoices.map((v) => v.replace(".pt", "")).join(", ")}`);
41522
+ }
41523
+ }
41524
+ }
41525
+ } catch {
41526
+ }
41527
+ }
41528
+ async function autoSetupPersonaPlex(onInfo) {
41529
+ const log = onInfo ?? (() => {
41530
+ });
41531
+ const caps = detectPersonaPlexCapability();
41532
+ if (!caps.supported) {
41533
+ log(`PersonaPlex not available: ${caps.reason}`);
41534
+ return null;
41535
+ }
41536
+ log(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB) \u2014 PersonaPlex compatible`);
41537
+ if (!isPersonaPlexInstalled()) {
41538
+ log("Installing PersonaPlex (first time setup)...");
41539
+ const ok = await installPersonaPlex(log);
41540
+ if (!ok) {
41541
+ log("PersonaPlex installation failed.");
41542
+ return null;
41543
+ }
41544
+ }
41545
+ const deployed = provisionShippedVoices(log);
41546
+ if (deployed > 0) {
41547
+ log(`Provisioned ${deployed} shipped voice(s)`);
41548
+ }
41549
+ patchFrontendVoiceList(log);
41550
+ if (isPersonaPlexRunning()) {
41551
+ const url = getPersonaPlexWSUrl();
41552
+ if (url) {
41553
+ log(`PersonaPlex already running at ${url}`);
41554
+ return url;
41555
+ }
41556
+ }
41557
+ return await startPersonaPlexDaemon(log);
41558
+ }
41559
+ var PERSONAPLEX_DIR, PID_FILE, PORT_FILE, LOG_FILE, CUSTOM_VOICES_DIR;
41560
+ var init_personaplex = __esm({
41561
+ "packages/cli/dist/tui/personaplex.js"() {
41562
+ "use strict";
41563
+ init_render();
41564
+ PERSONAPLEX_DIR = join54(homedir13(), ".open-agents", "voice", "personaplex");
41565
+ PID_FILE = join54(PERSONAPLEX_DIR, "daemon.pid");
41566
+ PORT_FILE = join54(PERSONAPLEX_DIR, "daemon.port");
41567
+ LOG_FILE = join54(PERSONAPLEX_DIR, "daemon.log");
41568
+ CUSTOM_VOICES_DIR = join54(PERSONAPLEX_DIR, "custom_voices");
41569
+ }
41570
+ });
41571
+
40727
41572
  // packages/cli/dist/tui/setup.js
40728
41573
  import * as readline from "node:readline";
40729
- import { execSync as execSync27, spawn as spawn19, exec as exec2 } from "node:child_process";
41574
+ import { execSync as execSync28, spawn as spawn20, exec as exec2 } from "node:child_process";
40730
41575
  import { promisify as promisify6 } from "node:util";
40731
- import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
40732
- import { join as join54 } from "node:path";
40733
- import { homedir as homedir13, platform as platform2 } from "node:os";
41576
+ import { existsSync as existsSync38, writeFileSync as writeFileSync17, readFileSync as readFileSync29, appendFileSync as appendFileSync2, mkdirSync as mkdirSync16 } from "node:fs";
41577
+ import { join as join55 } from "node:path";
41578
+ import { homedir as homedir14, platform as platform2 } from "node:os";
40734
41579
  async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
40735
41580
  if (_toolSupportCache.has(modelName))
40736
41581
  return _toolSupportCache.get(modelName);
@@ -40761,7 +41606,7 @@ function detectSystemSpecs() {
40761
41606
  let gpuVramGB = 0;
40762
41607
  let gpuName = "";
40763
41608
  try {
40764
- const memInfo = execSync27("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
41609
+ const memInfo = execSync28("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
40765
41610
  encoding: "utf8",
40766
41611
  timeout: 5e3
40767
41612
  });
@@ -40781,7 +41626,7 @@ function detectSystemSpecs() {
40781
41626
  } catch {
40782
41627
  }
40783
41628
  try {
40784
- const nvidiaSmi = execSync27("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
41629
+ const nvidiaSmi = execSync28("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
40785
41630
  const lines = nvidiaSmi.trim().split("\n");
40786
41631
  if (lines.length > 0) {
40787
41632
  for (const line of lines) {
@@ -40952,7 +41797,7 @@ function ensureCurl() {
40952
41797
  for (const s of strategies) {
40953
41798
  if (hasCmd(s.check)) {
40954
41799
  try {
40955
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
41800
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
40956
41801
  if (hasCmd("curl")) {
40957
41802
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
40958
41803
  `);
@@ -40966,7 +41811,7 @@ function ensureCurl() {
40966
41811
  }
40967
41812
  if (plat === "darwin") {
40968
41813
  try {
40969
- execSync27("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
41814
+ execSync28("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
40970
41815
  if (hasCmd("curl"))
40971
41816
  return true;
40972
41817
  } catch {
@@ -41001,7 +41846,7 @@ function installOllamaLinux() {
41001
41846
 
41002
41847
  `);
41003
41848
  try {
41004
- execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
41849
+ execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
41005
41850
  stdio: "inherit",
41006
41851
  timeout: 3e5
41007
41852
  });
@@ -41029,10 +41874,10 @@ async function installOllamaMac(_rl) {
41029
41874
 
41030
41875
  `);
41031
41876
  try {
41032
- execSync27('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
41877
+ execSync28('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
41033
41878
  if (!hasCmd("brew")) {
41034
41879
  try {
41035
- const brewPrefix = existsSync37("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
41880
+ const brewPrefix = existsSync38("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
41036
41881
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
41037
41882
  } catch {
41038
41883
  }
@@ -41062,7 +41907,7 @@ async function installOllamaMac(_rl) {
41062
41907
 
41063
41908
  `);
41064
41909
  try {
41065
- execSync27("brew install ollama", {
41910
+ execSync28("brew install ollama", {
41066
41911
  stdio: "inherit",
41067
41912
  timeout: 3e5
41068
41913
  });
@@ -41089,7 +41934,7 @@ function installOllamaWindows() {
41089
41934
 
41090
41935
  `);
41091
41936
  try {
41092
- execSync27('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
41937
+ execSync28('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
41093
41938
  stdio: "inherit",
41094
41939
  timeout: 3e5
41095
41940
  });
@@ -41140,7 +41985,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
41140
41985
  process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
41141
41986
  `);
41142
41987
  try {
41143
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
41988
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41144
41989
  child.unref();
41145
41990
  } catch {
41146
41991
  process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
@@ -41170,7 +42015,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
41170
42015
  }
41171
42016
  function pullModelWithAutoUpdate(tag) {
41172
42017
  try {
41173
- execSync27(`ollama pull ${tag}`, {
42018
+ execSync28(`ollama pull ${tag}`, {
41174
42019
  stdio: "inherit",
41175
42020
  timeout: 36e5
41176
42021
  // 1 hour max
@@ -41190,7 +42035,7 @@ function pullModelWithAutoUpdate(tag) {
41190
42035
 
41191
42036
  `);
41192
42037
  try {
41193
- execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
42038
+ execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
41194
42039
  stdio: "inherit",
41195
42040
  timeout: 3e5
41196
42041
  // 5 min max for install
@@ -41201,7 +42046,7 @@ function pullModelWithAutoUpdate(tag) {
41201
42046
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
41202
42047
 
41203
42048
  `);
41204
- execSync27(`ollama pull ${tag}`, {
42049
+ execSync28(`ollama pull ${tag}`, {
41205
42050
  stdio: "inherit",
41206
42051
  timeout: 36e5
41207
42052
  });
@@ -41303,7 +42148,7 @@ function ensurePython3() {
41303
42148
  if (plat === "darwin") {
41304
42149
  if (hasCmd("brew")) {
41305
42150
  try {
41306
- execSync27("brew install python3", { stdio: "inherit", timeout: 3e5 });
42151
+ execSync28("brew install python3", { stdio: "inherit", timeout: 3e5 });
41307
42152
  if (hasCmd("python3")) {
41308
42153
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
41309
42154
  `);
@@ -41316,7 +42161,7 @@ function ensurePython3() {
41316
42161
  for (const s of strategies) {
41317
42162
  if (hasCmd(s.check)) {
41318
42163
  try {
41319
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
42164
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
41320
42165
  if (hasCmd("python3") || hasCmd("python")) {
41321
42166
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
41322
42167
  `);
@@ -41332,11 +42177,11 @@ function ensurePython3() {
41332
42177
  }
41333
42178
  function checkPythonVenv() {
41334
42179
  try {
41335
- execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
42180
+ execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
41336
42181
  return true;
41337
42182
  } catch {
41338
42183
  try {
41339
- execSync27("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
42184
+ execSync28("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
41340
42185
  return true;
41341
42186
  } catch {
41342
42187
  return false;
@@ -41355,7 +42200,7 @@ function ensurePythonVenv() {
41355
42200
  for (const s of strategies) {
41356
42201
  if (hasCmd(s.check)) {
41357
42202
  try {
41358
- execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
42203
+ execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
41359
42204
  if (checkPythonVenv()) {
41360
42205
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
41361
42206
  `);
@@ -41513,6 +42358,20 @@ async function doSetup(config, rl) {
41513
42358
  } else {
41514
42359
  process.stdout.write(` ${c2.dim(" GPU:")} No NVIDIA GPU detected (CPU inference)
41515
42360
  `);
42361
+ }
42362
+ let personaPlexCapable = false;
42363
+ try {
42364
+ const { detectPersonaPlexCapability: detectPersonaPlexCapability2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
42365
+ const ppCaps = detectPersonaPlexCapability2();
42366
+ personaPlexCapable = ppCaps.supported;
42367
+ if (ppCaps.supported) {
42368
+ process.stdout.write(` ${c2.green("\u2714")} PersonaPlex full-duplex voice: ${c2.bold("compatible")} (${ppCaps.gpuName}, ${ppCaps.vramGB.toFixed(0)}GB VRAM)
42369
+ `);
42370
+ process.stdout.write(` ${c2.dim("Enable with: /voice personaplex")}
42371
+
42372
+ `);
42373
+ }
42374
+ } catch {
41516
42375
  }
41517
42376
  const score = computeInferenceScore(specs);
41518
42377
  const bw = 30;
@@ -41602,7 +42461,7 @@ async function doSetup(config, rl) {
41602
42461
  ${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
41603
42462
  `);
41604
42463
  try {
41605
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
42464
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41606
42465
  child.unref();
41607
42466
  await new Promise((resolve36) => setTimeout(resolve36, 3e3));
41608
42467
  try {
@@ -41630,7 +42489,7 @@ async function doSetup(config, rl) {
41630
42489
  ${c2.cyan("\u25CF")} Starting ollama serve...
41631
42490
  `);
41632
42491
  try {
41633
- const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
42492
+ const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
41634
42493
  child.unref();
41635
42494
  await new Promise((resolve36) => setTimeout(resolve36, 3e3));
41636
42495
  try {
@@ -41763,12 +42622,12 @@ async function doSetup(config, rl) {
41763
42622
  `PARAMETER num_predict ${numPredict}`,
41764
42623
  `PARAMETER stop "<|endoftext|>"`
41765
42624
  ].join("\n");
41766
- const modelDir2 = join54(homedir13(), ".open-agents", "models");
41767
- mkdirSync15(modelDir2, { recursive: true });
41768
- const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
41769
- writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
42625
+ const modelDir2 = join55(homedir14(), ".open-agents", "models");
42626
+ mkdirSync16(modelDir2, { recursive: true });
42627
+ const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
42628
+ writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
41770
42629
  process.stdout.write(` ${c2.dim("Creating model...")} `);
41771
- execSync27(`ollama create ${customName} -f ${modelfilePath}`, {
42630
+ execSync28(`ollama create ${customName} -f ${modelfilePath}`, {
41772
42631
  stdio: "pipe",
41773
42632
  timeout: 12e4
41774
42633
  });
@@ -41811,7 +42670,7 @@ async function isModelAvailable(config) {
41811
42670
  }
41812
42671
  function isFirstRun() {
41813
42672
  try {
41814
- return !existsSync37(join54(homedir13(), ".open-agents", "config.json"));
42673
+ return !existsSync38(join55(homedir14(), ".open-agents", "config.json"));
41815
42674
  } catch {
41816
42675
  return true;
41817
42676
  }
@@ -41819,7 +42678,7 @@ function isFirstRun() {
41819
42678
  function hasCmd(cmd) {
41820
42679
  try {
41821
42680
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
41822
- execSync27(whichCmd, { stdio: "pipe", timeout: 3e3 });
42681
+ execSync28(whichCmd, { stdio: "pipe", timeout: 3e3 });
41823
42682
  return true;
41824
42683
  } catch {
41825
42684
  return false;
@@ -41848,11 +42707,11 @@ function detectPkgManager() {
41848
42707
  return null;
41849
42708
  }
41850
42709
  function getVenvDir() {
41851
- return join54(homedir13(), ".open-agents", "venv");
42710
+ return join55(homedir14(), ".open-agents", "venv");
41852
42711
  }
41853
42712
  function hasVenvModule() {
41854
42713
  try {
41855
- execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
42714
+ execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
41856
42715
  return true;
41857
42716
  } catch {
41858
42717
  return false;
@@ -41861,9 +42720,9 @@ function hasVenvModule() {
41861
42720
  function ensureVenv(log) {
41862
42721
  const venvDir = getVenvDir();
41863
42722
  const isWin2 = process.platform === "win32";
41864
- const pipPath = isWin2 ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
42723
+ const pipPath = isWin2 ? join55(venvDir, "Scripts", "pip.exe") : join55(venvDir, "bin", "pip");
41865
42724
  const pythonCmd = isWin2 ? "python" : "python3";
41866
- if (existsSync37(pipPath))
42725
+ if (existsSync38(pipPath))
41867
42726
  return venvDir;
41868
42727
  log("Creating Python venv for vision deps...");
41869
42728
  if (!hasCmd(pythonCmd) && !hasCmd("python3")) {
@@ -41875,10 +42734,10 @@ function ensureVenv(log) {
41875
42734
  return null;
41876
42735
  }
41877
42736
  try {
41878
- mkdirSync15(join54(homedir13(), ".open-agents"), { recursive: true });
42737
+ mkdirSync16(join55(homedir14(), ".open-agents"), { recursive: true });
41879
42738
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
41880
- execSync27(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
41881
- execSync27(`"${pipPath}" install --upgrade pip`, {
42739
+ execSync28(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
42740
+ execSync28(`"${pipPath}" install --upgrade pip`, {
41882
42741
  stdio: "pipe",
41883
42742
  timeout: 6e4
41884
42743
  });
@@ -41891,7 +42750,7 @@ function ensureVenv(log) {
41891
42750
  }
41892
42751
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
41893
42752
  try {
41894
- execSync27(`sudo -n ${cmd}`, {
42753
+ execSync28(`sudo -n ${cmd}`, {
41895
42754
  stdio: "pipe",
41896
42755
  timeout: timeoutMs,
41897
42756
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -41904,7 +42763,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
41904
42763
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
41905
42764
  try {
41906
42765
  const escaped = cmd.replace(/'/g, "'\\''");
41907
- execSync27(`sudo -S bash -c '${escaped}'`, {
42766
+ execSync28(`sudo -S bash -c '${escaped}'`, {
41908
42767
  input: password + "\n",
41909
42768
  stdio: ["pipe", "pipe", "pipe"],
41910
42769
  timeout: timeoutMs,
@@ -42021,7 +42880,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42021
42880
  ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
42022
42881
  } else {
42023
42882
  try {
42024
- execSync27(batchCmd, { stdio: "pipe", timeout: 18e4 });
42883
+ execSync28(batchCmd, { stdio: "pipe", timeout: 18e4 });
42025
42884
  ok = true;
42026
42885
  } catch {
42027
42886
  ok = false;
@@ -42058,7 +42917,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42058
42917
  const venvCmds = {
42059
42918
  apt: () => {
42060
42919
  try {
42061
- const pyVer = execSync27(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
42920
+ const pyVer = execSync28(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
42062
42921
  return `apt-get install -y python3-venv python${pyVer}-venv`;
42063
42922
  } catch {
42064
42923
  return "apt-get install -y python3-venv";
@@ -42079,19 +42938,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42079
42938
  }
42080
42939
  }
42081
42940
  const venvDir = getVenvDir();
42082
- const venvBin = join54(venvDir, "bin");
42083
- const venvMoondream = join54(venvBin, "moondream-station");
42941
+ const venvBin = join55(venvDir, "bin");
42942
+ const venvMoondream = join55(venvBin, "moondream-station");
42084
42943
  const venv = ensureVenv(log);
42085
- if (venv && !hasCmd("moondream-station") && !existsSync37(venvMoondream)) {
42086
- const venvPip2 = join54(venvBin, "pip");
42944
+ if (venv && !hasCmd("moondream-station") && !existsSync38(venvMoondream)) {
42945
+ const venvPip2 = join55(venvBin, "pip");
42087
42946
  log("Installing moondream-station in ~/.open-agents/venv...");
42088
42947
  try {
42089
- execSync27(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
42090
- if (existsSync37(venvMoondream)) {
42948
+ execSync28(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
42949
+ if (existsSync38(venvMoondream)) {
42091
42950
  log("moondream-station installed successfully.");
42092
42951
  } else {
42093
42952
  try {
42094
- const check = execSync27(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
42953
+ const check = execSync28(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
42095
42954
  if (check.includes("moondream")) {
42096
42955
  log("moondream-station package installed.");
42097
42956
  }
@@ -42104,11 +42963,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42104
42963
  }
42105
42964
  }
42106
42965
  if (venv) {
42107
- const venvPython2 = join54(venvBin, "python");
42108
- const venvPip2 = join54(venvBin, "pip");
42966
+ const venvPython2 = join55(venvBin, "python");
42967
+ const venvPip2 = join55(venvBin, "pip");
42109
42968
  let ocrStackInstalled = false;
42110
42969
  try {
42111
- execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42970
+ execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42112
42971
  ocrStackInstalled = true;
42113
42972
  } catch {
42114
42973
  }
@@ -42116,9 +42975,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
42116
42975
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
42117
42976
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
42118
42977
  try {
42119
- execSync27(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
42978
+ execSync28(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
42120
42979
  try {
42121
- execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42980
+ execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
42122
42981
  log("OCR Python stack installed successfully.");
42123
42982
  } catch {
42124
42983
  log("OCR Python stack install completed but import verification failed.");
@@ -42152,9 +43011,9 @@ function ensureCloudflaredBackground(onInfo) {
42152
43011
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
42153
43012
  const cfArch = archMap[arch2] ?? "amd64";
42154
43013
  try {
42155
- 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 });
42156
- if (!process.env.PATH?.includes(`${homedir13()}/.local/bin`)) {
42157
- process.env.PATH = `${homedir13()}/.local/bin:${process.env.PATH}`;
43014
+ 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 });
43015
+ if (!process.env.PATH?.includes(`${homedir14()}/.local/bin`)) {
43016
+ process.env.PATH = `${homedir14()}/.local/bin:${process.env.PATH}`;
42158
43017
  }
42159
43018
  if (hasCmd("cloudflared")) {
42160
43019
  log("cloudflared installed.");
@@ -42163,7 +43022,7 @@ function ensureCloudflaredBackground(onInfo) {
42163
43022
  } catch {
42164
43023
  }
42165
43024
  try {
42166
- 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 });
43025
+ 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 });
42167
43026
  if (hasCmd("cloudflared")) {
42168
43027
  log("cloudflared installed.");
42169
43028
  return true;
@@ -42172,7 +43031,7 @@ function ensureCloudflaredBackground(onInfo) {
42172
43031
  }
42173
43032
  } else if (os === "darwin") {
42174
43033
  try {
42175
- execSync27("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
43034
+ execSync28("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
42176
43035
  if (hasCmd("cloudflared")) {
42177
43036
  log("cloudflared installed via Homebrew.");
42178
43037
  return true;
@@ -42249,10 +43108,10 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
42249
43108
  `PARAMETER num_predict ${numPredict}`,
42250
43109
  `PARAMETER stop "<|endoftext|>"`
42251
43110
  ].join("\n");
42252
- const modelDir2 = join54(homedir13(), ".open-agents", "models");
42253
- mkdirSync15(modelDir2, { recursive: true });
42254
- const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
42255
- writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
43111
+ const modelDir2 = join55(homedir14(), ".open-agents", "models");
43112
+ mkdirSync16(modelDir2, { recursive: true });
43113
+ const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
43114
+ writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
42256
43115
  await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
42257
43116
  timeout: 12e4
42258
43117
  });
@@ -42314,7 +43173,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
42314
43173
  }
42315
43174
  async function ensureNeovim() {
42316
43175
  try {
42317
- const nvimPath = execSync27("which nvim 2>/dev/null || where nvim 2>nul", {
43176
+ const nvimPath = execSync28("which nvim 2>/dev/null || where nvim 2>nul", {
42318
43177
  encoding: "utf8",
42319
43178
  stdio: "pipe",
42320
43179
  timeout: 5e3
@@ -42326,24 +43185,24 @@ async function ensureNeovim() {
42326
43185
  const platform6 = process.platform;
42327
43186
  const arch2 = process.arch;
42328
43187
  if (platform6 === "linux") {
42329
- const binDir = join54(homedir13(), ".local", "bin");
42330
- const nvimDest = join54(binDir, "nvim");
43188
+ const binDir = join55(homedir14(), ".local", "bin");
43189
+ const nvimDest = join55(binDir, "nvim");
42331
43190
  try {
42332
- mkdirSync15(binDir, { recursive: true });
43191
+ mkdirSync16(binDir, { recursive: true });
42333
43192
  } catch {
42334
43193
  }
42335
43194
  const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
42336
43195
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
42337
43196
  console.log(` Downloading Neovim (${appImageName})...`);
42338
43197
  try {
42339
- execSync27(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
42340
- execSync27(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
43198
+ execSync28(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
43199
+ execSync28(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
42341
43200
  } catch (err) {
42342
43201
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
42343
43202
  return null;
42344
43203
  }
42345
43204
  try {
42346
- const ver = execSync27(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
43205
+ const ver = execSync28(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
42347
43206
  console.log(` Installed: ${ver}`);
42348
43207
  } catch {
42349
43208
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -42358,8 +43217,8 @@ async function ensureNeovim() {
42358
43217
  if (hasCmd("brew")) {
42359
43218
  console.log(" Installing Neovim via Homebrew...");
42360
43219
  try {
42361
- execSync27("brew install neovim", { stdio: "inherit", timeout: 12e4 });
42362
- const nvimPath = execSync27("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
43220
+ execSync28("brew install neovim", { stdio: "inherit", timeout: 12e4 });
43221
+ const nvimPath = execSync28("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
42363
43222
  return nvimPath || null;
42364
43223
  } catch {
42365
43224
  console.log(" brew install neovim failed.");
@@ -42373,7 +43232,7 @@ async function ensureNeovim() {
42373
43232
  if (hasCmd("choco")) {
42374
43233
  console.log(" Installing Neovim via Chocolatey...");
42375
43234
  try {
42376
- execSync27("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
43235
+ execSync28("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
42377
43236
  return "nvim";
42378
43237
  } catch {
42379
43238
  console.log(" choco install neovim failed.");
@@ -42382,7 +43241,7 @@ async function ensureNeovim() {
42382
43241
  if (hasCmd("winget")) {
42383
43242
  console.log(" Installing Neovim via winget...");
42384
43243
  try {
42385
- execSync27("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
43244
+ execSync28("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
42386
43245
  stdio: "inherit",
42387
43246
  timeout: 12e4
42388
43247
  });
@@ -42398,9 +43257,9 @@ async function ensureNeovim() {
42398
43257
  }
42399
43258
  function ensurePathInShellRc(binDir) {
42400
43259
  const shell = process.env.SHELL ?? "";
42401
- const rcFile = shell.includes("zsh") ? join54(homedir13(), ".zshrc") : join54(homedir13(), ".bashrc");
43260
+ const rcFile = shell.includes("zsh") ? join55(homedir14(), ".zshrc") : join55(homedir14(), ".bashrc");
42402
43261
  try {
42403
- const rcContent = existsSync37(rcFile) ? readFileSync28(rcFile, "utf8") : "";
43262
+ const rcContent = existsSync38(rcFile) ? readFileSync29(rcFile, "utf8") : "";
42404
43263
  if (rcContent.includes(binDir))
42405
43264
  return;
42406
43265
  const exportLine = `
@@ -42438,7 +43297,7 @@ var init_setup = __esm({
42438
43297
  });
42439
43298
 
42440
43299
  // packages/cli/dist/tui/drop-panel.js
42441
- import { existsSync as existsSync38 } from "node:fs";
43300
+ import { existsSync as existsSync39 } from "node:fs";
42442
43301
  import { extname as extname10, resolve as resolve29 } from "node:path";
42443
43302
  function ansi4(code, text) {
42444
43303
  return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
@@ -42553,7 +43412,7 @@ function showDropPanel(opts) {
42553
43412
  filePath = decodeURIComponent(filePath.slice(7));
42554
43413
  }
42555
43414
  filePath = resolve29(filePath);
42556
- if (!existsSync38(filePath)) {
43415
+ if (!existsSync39(filePath)) {
42557
43416
  errorMsg = `File not found: ${filePath}`;
42558
43417
  render();
42559
43418
  return;
@@ -42624,10 +43483,10 @@ var init_drop_panel = __esm({
42624
43483
  });
42625
43484
 
42626
43485
  // packages/cli/dist/tui/neovim-mode.js
42627
- import { existsSync as existsSync39, unlinkSync as unlinkSync8 } from "node:fs";
43486
+ import { existsSync as existsSync40, unlinkSync as unlinkSync8 } from "node:fs";
42628
43487
  import { tmpdir as tmpdir8 } from "node:os";
42629
- import { join as join55 } from "node:path";
42630
- import { execSync as execSync28 } from "node:child_process";
43488
+ import { join as join56 } from "node:path";
43489
+ import { execSync as execSync29 } from "node:child_process";
42631
43490
  function isNeovimActive() {
42632
43491
  return _state !== null && !_state.cleanedUp;
42633
43492
  }
@@ -42645,7 +43504,7 @@ async function startNeovimMode(opts) {
42645
43504
  }
42646
43505
  let nvimPath;
42647
43506
  try {
42648
- nvimPath = execSync28("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
43507
+ nvimPath = execSync29("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
42649
43508
  if (!nvimPath)
42650
43509
  throw new Error();
42651
43510
  } catch {
@@ -42674,9 +43533,9 @@ async function startNeovimMode(opts) {
42674
43533
  );
42675
43534
  } catch {
42676
43535
  }
42677
- const socketPath = join55(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
43536
+ const socketPath = join56(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
42678
43537
  try {
42679
- if (existsSync39(socketPath))
43538
+ if (existsSync40(socketPath))
42680
43539
  unlinkSync8(socketPath);
42681
43540
  } catch {
42682
43541
  }
@@ -42903,13 +43762,13 @@ function resizeNeovim(cols, contentRows) {
42903
43762
  }
42904
43763
  async function connectRPC(state, neovimPkg, cols) {
42905
43764
  let attempts = 0;
42906
- while (!existsSync39(state.socketPath) && attempts < 30) {
43765
+ while (!existsSync40(state.socketPath) && attempts < 30) {
42907
43766
  await new Promise((r) => setTimeout(r, 200));
42908
43767
  attempts++;
42909
43768
  if (state.cleanedUp)
42910
43769
  return;
42911
43770
  }
42912
- if (!existsSync39(state.socketPath))
43771
+ if (!existsSync40(state.socketPath))
42913
43772
  return;
42914
43773
  const nvim = neovimPkg.attach({ socket: state.socketPath });
42915
43774
  state.nvim = nvim;
@@ -43046,7 +43905,7 @@ function doCleanup(state) {
43046
43905
  state.pty = null;
43047
43906
  }
43048
43907
  try {
43049
- if (existsSync39(state.socketPath))
43908
+ if (existsSync40(state.socketPath))
43050
43909
  unlinkSync8(state.socketPath);
43051
43910
  } catch {
43052
43911
  }
@@ -43481,8 +44340,8 @@ __export(sponsor_wizard_exports, {
43481
44340
  saveSponsorConfig: () => saveSponsorConfig,
43482
44341
  showSponsorDashboard: () => showSponsorDashboard
43483
44342
  });
43484
- import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync16 } from "node:fs";
43485
- import { join as join56 } from "node:path";
44343
+ import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17 } from "node:fs";
44344
+ import { join as join57 } from "node:path";
43486
44345
  function colorPreview(code) {
43487
44346
  return `\x1B[38;5;${code}m\u2588\u2588\u2588\u2588\x1B[0m (${code})`;
43488
44347
  }
@@ -43495,26 +44354,26 @@ function gradientPreview(start, end) {
43495
44354
  return s;
43496
44355
  }
43497
44356
  function sponsorDir(projectDir) {
43498
- return join56(projectDir, ".oa", "sponsor");
44357
+ return join57(projectDir, ".oa", "sponsor");
43499
44358
  }
43500
44359
  function configPath(projectDir) {
43501
- return join56(sponsorDir(projectDir), "config.json");
44360
+ return join57(sponsorDir(projectDir), "config.json");
43502
44361
  }
43503
44362
  function loadSponsorConfig(projectDir) {
43504
44363
  const p = configPath(projectDir);
43505
- if (!existsSync40(p))
44364
+ if (!existsSync41(p))
43506
44365
  return null;
43507
44366
  try {
43508
- return JSON.parse(readFileSync29(p, "utf8"));
44367
+ return JSON.parse(readFileSync30(p, "utf8"));
43509
44368
  } catch {
43510
44369
  return null;
43511
44370
  }
43512
44371
  }
43513
44372
  function saveSponsorConfig(projectDir, config) {
43514
44373
  const dir = sponsorDir(projectDir);
43515
- mkdirSync16(dir, { recursive: true });
44374
+ mkdirSync17(dir, { recursive: true });
43516
44375
  config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
43517
- writeFileSync17(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
44376
+ writeFileSync18(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
43518
44377
  }
43519
44378
  function defaultConfig() {
43520
44379
  return {
@@ -44217,10 +45076,10 @@ __export(voice_exports, {
44217
45076
  registerCustomOnnxModel: () => registerCustomOnnxModel,
44218
45077
  resetNarrationContext: () => resetNarrationContext
44219
45078
  });
44220
- 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";
44221
- import { join as join57, dirname as dirname18 } from "node:path";
44222
- import { homedir as homedir14, tmpdir as tmpdir9, platform as platform3 } from "node:os";
44223
- import { execSync as execSync29, spawn as nodeSpawn } from "node:child_process";
45079
+ import { existsSync as existsSync42, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, readFileSync as readFileSync31, unlinkSync as unlinkSync9, readdirSync as readdirSync12, renameSync, statSync as statSync13 } from "node:fs";
45080
+ import { join as join58, dirname as dirname19 } from "node:path";
45081
+ import { homedir as homedir15, tmpdir as tmpdir9, platform as platform3 } from "node:os";
45082
+ import { execSync as execSync30, spawn as nodeSpawn } from "node:child_process";
44224
45083
  import { createRequire } from "node:module";
44225
45084
  function sanitizeForTTS(text) {
44226
45085
  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();
@@ -44243,40 +45102,40 @@ function listVoiceModels() {
44243
45102
  }));
44244
45103
  }
44245
45104
  function voiceDir() {
44246
- return join57(homedir14(), ".open-agents", "voice");
45105
+ return join58(homedir15(), ".open-agents", "voice");
44247
45106
  }
44248
45107
  function modelsDir() {
44249
- return join57(voiceDir(), "models");
45108
+ return join58(voiceDir(), "models");
44250
45109
  }
44251
45110
  function modelDir(id) {
44252
- return join57(modelsDir(), id);
45111
+ return join58(modelsDir(), id);
44253
45112
  }
44254
45113
  function modelOnnxPath(id) {
44255
- return join57(modelDir(id), "model.onnx");
45114
+ return join58(modelDir(id), "model.onnx");
44256
45115
  }
44257
45116
  function modelConfigPath(id) {
44258
- return join57(modelDir(id), "config.json");
45117
+ return join58(modelDir(id), "config.json");
44259
45118
  }
44260
45119
  function luxttsVenvDir() {
44261
- return join57(voiceDir(), "luxtts-venv");
45120
+ return join58(voiceDir(), "luxtts-venv");
44262
45121
  }
44263
45122
  function luxttsVenvPy() {
44264
- return platform3() === "win32" ? join57(luxttsVenvDir(), "Scripts", "python.exe") : join57(luxttsVenvDir(), "bin", "python3");
45123
+ return platform3() === "win32" ? join58(luxttsVenvDir(), "Scripts", "python.exe") : join58(luxttsVenvDir(), "bin", "python3");
44265
45124
  }
44266
45125
  function luxttsRepoDir() {
44267
- return join57(voiceDir(), "LuxTTS");
45126
+ return join58(voiceDir(), "LuxTTS");
44268
45127
  }
44269
45128
  function luxttsCloneRefsDir() {
44270
- return join57(voiceDir(), "clone-refs");
45129
+ return join58(voiceDir(), "clone-refs");
44271
45130
  }
44272
45131
  function luxttsInferScript() {
44273
- return join57(voiceDir(), "luxtts-infer.py");
45132
+ return join58(voiceDir(), "luxtts-infer.py");
44274
45133
  }
44275
45134
  function writeDetectTorchScript(targetPath) {
44276
- if (existsSync41(targetPath))
45135
+ if (existsSync42(targetPath))
44277
45136
  return;
44278
45137
  try {
44279
- mkdirSync17(dirname18(targetPath), { recursive: true });
45138
+ mkdirSync18(dirname19(targetPath), { recursive: true });
44280
45139
  } catch {
44281
45140
  }
44282
45141
  const script = `#!/usr/bin/env python3
@@ -44349,7 +45208,7 @@ def main():
44349
45208
  if __name__ == "__main__": main()
44350
45209
  `;
44351
45210
  try {
44352
- writeFileSync18(targetPath, script, { mode: 493 });
45211
+ writeFileSync19(targetPath, script, { mode: 493 });
44353
45212
  } catch {
44354
45213
  }
44355
45214
  }
@@ -45159,8 +46018,8 @@ var init_voice = __esm({
45159
46018
  const refsDir = luxttsCloneRefsDir();
45160
46019
  const targets = ["glados", "overwatch"];
45161
46020
  for (const modelId of targets) {
45162
- const refFile = join57(refsDir, `${modelId}-ref.wav`);
45163
- if (existsSync41(refFile))
46021
+ const refFile = join58(refsDir, `${modelId}-ref.wav`);
46022
+ if (existsSync42(refFile))
45164
46023
  continue;
45165
46024
  try {
45166
46025
  await this.generateCloneRef(modelId);
@@ -45239,24 +46098,24 @@ var init_voice = __esm({
45239
46098
  }
45240
46099
  p = p.replace(/\\ /g, " ");
45241
46100
  if (p.startsWith("~/") || p === "~") {
45242
- p = join57(homedir14(), p.slice(1));
46101
+ p = join58(homedir15(), p.slice(1));
45243
46102
  }
45244
- if (!existsSync41(p)) {
46103
+ if (!existsSync42(p)) {
45245
46104
  return `File not found: ${p}
45246
46105
  (original input: ${audioPath})`;
45247
46106
  }
45248
46107
  audioPath = p;
45249
46108
  const refsDir = luxttsCloneRefsDir();
45250
- if (!existsSync41(refsDir))
45251
- mkdirSync17(refsDir, { recursive: true });
46109
+ if (!existsSync42(refsDir))
46110
+ mkdirSync18(refsDir, { recursive: true });
45252
46111
  const ext = audioPath.split(".").pop() || "wav";
45253
46112
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
45254
46113
  const ts = Date.now().toString(36);
45255
46114
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
45256
- const destPath = join57(refsDir, destFilename);
46115
+ const destPath = join58(refsDir, destFilename);
45257
46116
  try {
45258
- const data = readFileSync30(audioPath);
45259
- writeFileSync18(destPath, data);
46117
+ const data = readFileSync31(audioPath);
46118
+ writeFileSync19(destPath, data);
45260
46119
  } catch (err) {
45261
46120
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
45262
46121
  }
@@ -45296,9 +46155,9 @@ var init_voice = __esm({
45296
46155
  return `Failed to synthesize reference audio from ${source.label}.`;
45297
46156
  }
45298
46157
  const refsDir = luxttsCloneRefsDir();
45299
- if (!existsSync41(refsDir))
45300
- mkdirSync17(refsDir, { recursive: true });
45301
- const destPath = join57(refsDir, `${sourceModelId}-ref.wav`);
46158
+ if (!existsSync42(refsDir))
46159
+ mkdirSync18(refsDir, { recursive: true });
46160
+ const destPath = join58(refsDir, `${sourceModelId}-ref.wav`);
45302
46161
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
45303
46162
  this.writeWav(audioData, sampleRate, destPath);
45304
46163
  this.luxttsCloneRef = destPath;
@@ -45314,23 +46173,23 @@ var init_voice = __esm({
45314
46173
  // -------------------------------------------------------------------------
45315
46174
  /** Metadata file for friendly names of clone refs */
45316
46175
  static cloneMetaFile() {
45317
- return join57(luxttsCloneRefsDir(), "meta.json");
46176
+ return join58(luxttsCloneRefsDir(), "meta.json");
45318
46177
  }
45319
46178
  loadCloneMeta() {
45320
46179
  const p = _VoiceEngine.cloneMetaFile();
45321
- if (!existsSync41(p))
46180
+ if (!existsSync42(p))
45322
46181
  return {};
45323
46182
  try {
45324
- return JSON.parse(readFileSync30(p, "utf8"));
46183
+ return JSON.parse(readFileSync31(p, "utf8"));
45325
46184
  } catch {
45326
46185
  return {};
45327
46186
  }
45328
46187
  }
45329
46188
  saveCloneMeta(meta) {
45330
46189
  const dir = luxttsCloneRefsDir();
45331
- if (!existsSync41(dir))
45332
- mkdirSync17(dir, { recursive: true });
45333
- writeFileSync18(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
46190
+ if (!existsSync42(dir))
46191
+ mkdirSync18(dir, { recursive: true });
46192
+ writeFileSync19(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
45334
46193
  }
45335
46194
  /** Audio file extensions recognized as clone references */
45336
46195
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -45340,15 +46199,15 @@ var init_voice = __esm({
45340
46199
  */
45341
46200
  listCloneRefs() {
45342
46201
  const dir = luxttsCloneRefsDir();
45343
- if (!existsSync41(dir))
46202
+ if (!existsSync42(dir))
45344
46203
  return [];
45345
46204
  const meta = this.loadCloneMeta();
45346
- const files = readdirSync11(dir).filter((f) => {
46205
+ const files = readdirSync12(dir).filter((f) => {
45347
46206
  const ext = f.split(".").pop()?.toLowerCase() ?? "";
45348
46207
  return _VoiceEngine.AUDIO_EXTS.has(ext);
45349
46208
  });
45350
46209
  return files.map((f) => {
45351
- const p = join57(dir, f);
46210
+ const p = join58(dir, f);
45352
46211
  let size = 0;
45353
46212
  try {
45354
46213
  size = statSync13(p).size;
@@ -45365,8 +46224,8 @@ var init_voice = __esm({
45365
46224
  }
45366
46225
  /** Delete a clone reference file by filename. Returns true if deleted. */
45367
46226
  deleteCloneRef(filename) {
45368
- const p = join57(luxttsCloneRefsDir(), filename);
45369
- if (!existsSync41(p))
46227
+ const p = join58(luxttsCloneRefsDir(), filename);
46228
+ if (!existsSync42(p))
45370
46229
  return false;
45371
46230
  try {
45372
46231
  unlinkSync9(p);
@@ -45390,8 +46249,8 @@ var init_voice = __esm({
45390
46249
  }
45391
46250
  /** Set the active clone reference by filename. */
45392
46251
  setActiveCloneRef(filename) {
45393
- const p = join57(luxttsCloneRefsDir(), filename);
45394
- if (!existsSync41(p))
46252
+ const p = join58(luxttsCloneRefsDir(), filename);
46253
+ if (!existsSync42(p))
45395
46254
  return `File not found: ${filename}`;
45396
46255
  this.luxttsCloneRef = p;
45397
46256
  return `Active clone voice set to: ${filename}`;
@@ -45716,7 +46575,7 @@ var init_voice = __esm({
45716
46575
  }
45717
46576
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
45718
46577
  }
45719
- const wavPath = join57(tmpdir9(), `oa-voice-${Date.now()}.wav`);
46578
+ const wavPath = join58(tmpdir9(), `oa-voice-${Date.now()}.wav`);
45720
46579
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
45721
46580
  await this.playWav(wavPath);
45722
46581
  try {
@@ -45833,7 +46692,7 @@ var init_voice = __esm({
45833
46692
  buffer.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
45834
46693
  pos += 2;
45835
46694
  }
45836
- writeFileSync18(path, buffer);
46695
+ writeFileSync19(path, buffer);
45837
46696
  }
45838
46697
  // -------------------------------------------------------------------------
45839
46698
  // Phonemization
@@ -45911,7 +46770,7 @@ var init_voice = __esm({
45911
46770
  return buffer;
45912
46771
  }
45913
46772
  writeWav(samples, sampleRate, path) {
45914
- writeFileSync18(path, this.buildWavBuffer(samples, sampleRate));
46773
+ writeFileSync19(path, this.buildWavBuffer(samples, sampleRate));
45915
46774
  }
45916
46775
  // -------------------------------------------------------------------------
45917
46776
  // Audio playback (system default speakers)
@@ -45961,7 +46820,7 @@ var init_voice = __esm({
45961
46820
  }
45962
46821
  for (const player of ["paplay", "pw-play", "aplay"]) {
45963
46822
  try {
45964
- execSync29(`which ${player}`, { stdio: "pipe" });
46823
+ execSync30(`which ${player}`, { stdio: "pipe" });
45965
46824
  return [player, path];
45966
46825
  } catch {
45967
46826
  }
@@ -45990,7 +46849,7 @@ var init_voice = __esm({
45990
46849
  return this.python3Path;
45991
46850
  for (const bin of ["python3", "python"]) {
45992
46851
  try {
45993
- const path = execSync29(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
46852
+ const path = execSync30(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
45994
46853
  if (path) {
45995
46854
  this.python3Path = path;
45996
46855
  return path;
@@ -46056,7 +46915,7 @@ var init_voice = __esm({
46056
46915
  return false;
46057
46916
  }
46058
46917
  try {
46059
- execSync29(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
46918
+ execSync30(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
46060
46919
  this.mlxInstalled = true;
46061
46920
  return true;
46062
46921
  } catch {
@@ -46109,7 +46968,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46109
46968
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
46110
46969
  const mlxVoice = model.mlxVoice ?? "af_heart";
46111
46970
  const mlxLangCode = model.mlxLangCode ?? "a";
46112
- const wavPath = join57(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
46971
+ const wavPath = join58(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
46113
46972
  const pyScript = [
46114
46973
  "import sys, json",
46115
46974
  "from mlx_audio.tts import generate as tts_gen",
@@ -46117,20 +46976,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46117
46976
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
46118
46977
  ].join("; ");
46119
46978
  try {
46120
- execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46979
+ execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46121
46980
  } catch (err) {
46122
46981
  try {
46123
46982
  const safeText = cleaned.replace(/'/g, "'\\''");
46124
- 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() });
46983
+ 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() });
46125
46984
  } catch (err2) {
46126
46985
  return;
46127
46986
  }
46128
46987
  }
46129
- if (!existsSync41(wavPath))
46988
+ if (!existsSync42(wavPath))
46130
46989
  return;
46131
46990
  if (volume !== 1) {
46132
46991
  try {
46133
- const wavData = readFileSync30(wavPath);
46992
+ const wavData = readFileSync31(wavPath);
46134
46993
  if (wavData.length > 44) {
46135
46994
  const header = wavData.subarray(0, 44);
46136
46995
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -46138,14 +46997,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46138
46997
  samples[i] = Math.round(samples[i] * volume);
46139
46998
  }
46140
46999
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
46141
- writeFileSync18(wavPath, scaled);
47000
+ writeFileSync19(wavPath, scaled);
46142
47001
  }
46143
47002
  } catch {
46144
47003
  }
46145
47004
  }
46146
47005
  if (this.onPCMOutput) {
46147
47006
  try {
46148
- const wavData = readFileSync30(wavPath);
47007
+ const wavData = readFileSync31(wavPath);
46149
47008
  if (wavData.length > 44) {
46150
47009
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
46151
47010
  const sampleRate = wavData.readUInt32LE(24);
@@ -46177,7 +47036,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46177
47036
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
46178
47037
  const mlxVoice = model.mlxVoice ?? "af_heart";
46179
47038
  const mlxLangCode = model.mlxLangCode ?? "a";
46180
- const wavPath = join57(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
47039
+ const wavPath = join58(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
46181
47040
  const pyScript = [
46182
47041
  "import sys, json",
46183
47042
  "from mlx_audio.tts import generate as tts_gen",
@@ -46185,19 +47044,19 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46185
47044
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
46186
47045
  ].join("; ");
46187
47046
  try {
46188
- execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
47047
+ execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
46189
47048
  } catch {
46190
47049
  try {
46191
47050
  const safeText = cleaned.replace(/'/g, "'\\''");
46192
- 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() });
47051
+ 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() });
46193
47052
  } catch {
46194
47053
  return null;
46195
47054
  }
46196
47055
  }
46197
- if (!existsSync41(wavPath))
47056
+ if (!existsSync42(wavPath))
46198
47057
  return null;
46199
47058
  try {
46200
- const data = readFileSync30(wavPath);
47059
+ const data = readFileSync31(wavPath);
46201
47060
  unlinkSync9(wavPath);
46202
47061
  return data;
46203
47062
  } catch {
@@ -46220,7 +47079,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46220
47079
  }
46221
47080
  const venvDir = luxttsVenvDir();
46222
47081
  const venvPy = luxttsVenvPy();
46223
- if (existsSync41(venvPy)) {
47082
+ if (existsSync42(venvPy)) {
46224
47083
  try {
46225
47084
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
46226
47085
  let hasCudaSys = false;
@@ -46234,7 +47093,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46234
47093
  if (torchCheck === "cpu") {
46235
47094
  renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
46236
47095
  try {
46237
- const detectScript = join57(voiceDir(), "detect-torch.py");
47096
+ const detectScript = join58(voiceDir(), "detect-torch.py");
46238
47097
  writeDetectTorchScript(detectScript);
46239
47098
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
46240
47099
  try {
@@ -46259,7 +47118,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46259
47118
  }
46260
47119
  }
46261
47120
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
46262
- if (!existsSync41(venvDir)) {
47121
+ if (!existsSync42(venvDir)) {
46263
47122
  renderInfo(" Creating Python virtual environment...");
46264
47123
  try {
46265
47124
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -46268,7 +47127,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46268
47127
  }
46269
47128
  }
46270
47129
  {
46271
- const detectScript = join57(voiceDir(), "detect-torch.py");
47130
+ const detectScript = join58(voiceDir(), "detect-torch.py");
46272
47131
  writeDetectTorchScript(detectScript);
46273
47132
  let pipArgsStr = "torch torchaudio";
46274
47133
  let torchDesc = "unknown platform";
@@ -46305,10 +47164,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46305
47164
  }
46306
47165
  }
46307
47166
  const repoDir = luxttsRepoDir();
46308
- if (!existsSync41(join57(repoDir, "zipvoice", "luxvoice.py"))) {
47167
+ if (!existsSync42(join58(repoDir, "zipvoice", "luxvoice.py"))) {
46309
47168
  renderInfo(" Cloning LuxTTS repository...");
46310
47169
  try {
46311
- if (existsSync41(repoDir)) {
47170
+ if (existsSync42(repoDir)) {
46312
47171
  const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
46313
47172
  await this.asyncShell(rmCmd, 3e4);
46314
47173
  }
@@ -46387,7 +47246,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46387
47246
  renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
46388
47247
  }
46389
47248
  }
46390
- const isJetson = isArm && (existsSync41("/etc/nv_tegra_release") || existsSync41("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
47249
+ const isJetson = isArm && (existsSync42("/etc/nv_tegra_release") || existsSync42("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
46391
47250
  const installSteps = isArm ? [
46392
47251
  // ARM: install individually so we get clear error messages per package.
46393
47252
  // ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
@@ -46457,14 +47316,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
46457
47316
  }
46458
47317
  /** Auto-detect an existing clone reference in the refs directory */
46459
47318
  autoDetectCloneRef() {
46460
- if (this.luxttsCloneRef && existsSync41(this.luxttsCloneRef))
47319
+ if (this.luxttsCloneRef && existsSync42(this.luxttsCloneRef))
46461
47320
  return;
46462
47321
  const refsDir = luxttsCloneRefsDir();
46463
- if (!existsSync41(refsDir))
47322
+ if (!existsSync42(refsDir))
46464
47323
  return;
46465
47324
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
46466
- const p = join57(refsDir, name);
46467
- if (existsSync41(p)) {
47325
+ const p = join58(refsDir, name);
47326
+ if (existsSync42(p)) {
46468
47327
  this.luxttsCloneRef = p;
46469
47328
  return;
46470
47329
  }
@@ -46564,15 +47423,15 @@ if __name__ == '__main__':
46564
47423
  main()
46565
47424
  `;
46566
47425
  const scriptPath2 = luxttsInferScript();
46567
- mkdirSync17(voiceDir(), { recursive: true });
46568
- writeFileSync18(scriptPath2, script);
47426
+ mkdirSync18(voiceDir(), { recursive: true });
47427
+ writeFileSync19(scriptPath2, script);
46569
47428
  }
46570
47429
  /** Ensure the LuxTTS daemon is running, spawn if needed */
46571
47430
  async ensureLuxttsDaemon() {
46572
47431
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
46573
47432
  return true;
46574
47433
  const venvPy = luxttsVenvPy();
46575
- if (!existsSync41(venvPy))
47434
+ if (!existsSync42(venvPy))
46576
47435
  return false;
46577
47436
  return new Promise((resolve36) => {
46578
47437
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
@@ -46656,7 +47515,7 @@ if __name__ == '__main__':
46656
47515
  * Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
46657
47516
  */
46658
47517
  async synthesizeLuxttsWav(text, speedFactor = 1) {
46659
- if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
47518
+ if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
46660
47519
  return null;
46661
47520
  const cleaned = text.replace(/\*/g, "").trim();
46662
47521
  if (!cleaned)
@@ -46664,7 +47523,7 @@ if __name__ == '__main__':
46664
47523
  const ready = await this.ensureLuxttsDaemon();
46665
47524
  if (!ready)
46666
47525
  return null;
46667
- const wavPath = join57(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
47526
+ const wavPath = join58(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
46668
47527
  try {
46669
47528
  await this.luxttsRequest({
46670
47529
  action: "synthesize",
@@ -46676,17 +47535,17 @@ if __name__ == '__main__':
46676
47535
  } catch {
46677
47536
  return null;
46678
47537
  }
46679
- return existsSync41(wavPath) ? wavPath : null;
47538
+ return existsSync42(wavPath) ? wavPath : null;
46680
47539
  }
46681
47540
  /**
46682
47541
  * Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
46683
47542
  * Cleans up the WAV file after playback.
46684
47543
  */
46685
47544
  async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
46686
- if (!existsSync41(wavPath))
47545
+ if (!existsSync42(wavPath))
46687
47546
  return;
46688
47547
  try {
46689
- const wavData = readFileSync30(wavPath);
47548
+ const wavData = readFileSync31(wavPath);
46690
47549
  if (wavData.length > 44) {
46691
47550
  const sampleRate = wavData.readUInt32LE(24);
46692
47551
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -46701,13 +47560,13 @@ if __name__ == '__main__':
46701
47560
  }
46702
47561
  const header = wavData.subarray(0, 44);
46703
47562
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
46704
- writeFileSync18(wavPath, scaled);
47563
+ writeFileSync19(wavPath, scaled);
46705
47564
  }
46706
47565
  } catch {
46707
47566
  }
46708
47567
  if (pitchFactor !== 1) {
46709
47568
  try {
46710
- const wavData = readFileSync30(wavPath);
47569
+ const wavData = readFileSync31(wavPath);
46711
47570
  if (wavData.length > 44) {
46712
47571
  const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
46713
47572
  const float32 = new Float32Array(int16.length);
@@ -46722,7 +47581,7 @@ if __name__ == '__main__':
46722
47581
  }
46723
47582
  if (this.onPCMOutput) {
46724
47583
  try {
46725
- const wavData = readFileSync30(wavPath);
47584
+ const wavData = readFileSync31(wavPath);
46726
47585
  if (wavData.length > 44) {
46727
47586
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
46728
47587
  const sampleRate = wavData.readUInt32LE(24);
@@ -46733,7 +47592,7 @@ if __name__ == '__main__':
46733
47592
  }
46734
47593
  if (stereoDelayMs > 0) {
46735
47594
  try {
46736
- const wavData = readFileSync30(wavPath);
47595
+ const wavData = readFileSync31(wavPath);
46737
47596
  if (wavData.length > 44) {
46738
47597
  const sampleRate = wavData.readUInt32LE(24);
46739
47598
  const numChannels = wavData.readUInt16LE(22);
@@ -46769,7 +47628,7 @@ if __name__ == '__main__':
46769
47628
  * Used for Telegram voice messages and WebSocket streaming.
46770
47629
  */
46771
47630
  async synthesizeLuxttsToBuffer(text) {
46772
- if (!this.luxttsCloneRef || !existsSync41(this.luxttsCloneRef))
47631
+ if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
46773
47632
  return null;
46774
47633
  const cleaned = text.replace(/\*/g, "").trim();
46775
47634
  if (!cleaned)
@@ -46777,7 +47636,7 @@ if __name__ == '__main__':
46777
47636
  const ready = await this.ensureLuxttsDaemon();
46778
47637
  if (!ready)
46779
47638
  return null;
46780
- const wavPath = join57(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
47639
+ const wavPath = join58(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
46781
47640
  try {
46782
47641
  await this.luxttsRequest({
46783
47642
  action: "synthesize",
@@ -46789,10 +47648,10 @@ if __name__ == '__main__':
46789
47648
  } catch {
46790
47649
  return null;
46791
47650
  }
46792
- if (!existsSync41(wavPath))
47651
+ if (!existsSync42(wavPath))
46793
47652
  return null;
46794
47653
  try {
46795
- const data = readFileSync30(wavPath);
47654
+ const data = readFileSync31(wavPath);
46796
47655
  unlinkSync9(wavPath);
46797
47656
  return data;
46798
47657
  } catch {
@@ -46806,40 +47665,40 @@ if __name__ == '__main__':
46806
47665
  if (this.ort)
46807
47666
  return;
46808
47667
  const arch2 = process.arch;
46809
- mkdirSync17(voiceDir(), { recursive: true });
46810
- const pkgPath = join57(voiceDir(), "package.json");
47668
+ mkdirSync18(voiceDir(), { recursive: true });
47669
+ const pkgPath = join58(voiceDir(), "package.json");
46811
47670
  const expectedDeps = {
46812
47671
  "onnxruntime-node": "^1.21.0",
46813
47672
  "phonemizer": "^1.2.1"
46814
47673
  };
46815
- if (existsSync41(pkgPath)) {
47674
+ if (existsSync42(pkgPath)) {
46816
47675
  try {
46817
- const existing = JSON.parse(readFileSync30(pkgPath, "utf8"));
47676
+ const existing = JSON.parse(readFileSync31(pkgPath, "utf8"));
46818
47677
  if (!existing.dependencies?.["phonemizer"]) {
46819
47678
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
46820
- writeFileSync18(pkgPath, JSON.stringify(existing, null, 2));
47679
+ writeFileSync19(pkgPath, JSON.stringify(existing, null, 2));
46821
47680
  }
46822
47681
  } catch {
46823
47682
  }
46824
47683
  }
46825
- if (!existsSync41(pkgPath)) {
46826
- writeFileSync18(pkgPath, JSON.stringify({
47684
+ if (!existsSync42(pkgPath)) {
47685
+ writeFileSync19(pkgPath, JSON.stringify({
46827
47686
  name: "open-agents-voice",
46828
47687
  private: true,
46829
47688
  dependencies: expectedDeps
46830
47689
  }, null, 2));
46831
47690
  }
46832
- const voiceRequire = createRequire(join57(voiceDir(), "index.js"));
47691
+ const voiceRequire = createRequire(join58(voiceDir(), "index.js"));
46833
47692
  const probeOnnx = async () => {
46834
47693
  try {
46835
- 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);
47694
+ 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);
46836
47695
  return output.trim() === "OK";
46837
47696
  } catch {
46838
47697
  return false;
46839
47698
  }
46840
47699
  };
46841
- const onnxNodeModules = join57(voiceDir(), "node_modules", "onnxruntime-node");
46842
- const onnxInstalled = existsSync41(onnxNodeModules);
47700
+ const onnxNodeModules = join58(voiceDir(), "node_modules", "onnxruntime-node");
47701
+ const onnxInstalled = existsSync42(onnxNodeModules);
46843
47702
  if (onnxInstalled && !await probeOnnx()) {
46844
47703
  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.`);
46845
47704
  }
@@ -46889,18 +47748,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46889
47748
  const dir = modelDir(id);
46890
47749
  const onnxPath = modelOnnxPath(id);
46891
47750
  const configPath2 = modelConfigPath(id);
46892
- if (existsSync41(onnxPath) && existsSync41(configPath2))
47751
+ if (existsSync42(onnxPath) && existsSync42(configPath2))
46893
47752
  return;
46894
- mkdirSync17(dir, { recursive: true });
46895
- if (!existsSync41(configPath2)) {
47753
+ mkdirSync18(dir, { recursive: true });
47754
+ if (!existsSync42(configPath2)) {
46896
47755
  renderInfo(`Downloading ${model.label} voice config...`);
46897
47756
  const configResp = await fetch(model.configUrl);
46898
47757
  if (!configResp.ok)
46899
47758
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
46900
47759
  const configText = await configResp.text();
46901
- writeFileSync18(configPath2, configText);
47760
+ writeFileSync19(configPath2, configText);
46902
47761
  }
46903
- if (!existsSync41(onnxPath)) {
47762
+ if (!existsSync42(onnxPath)) {
46904
47763
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
46905
47764
  const onnxResp = await fetch(model.onnxUrl);
46906
47765
  if (!onnxResp.ok)
@@ -46925,7 +47784,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46925
47784
  }
46926
47785
  }
46927
47786
  const fullBuffer = Buffer.concat(chunks);
46928
- writeFileSync18(onnxPath, fullBuffer);
47787
+ writeFileSync19(onnxPath, fullBuffer);
46929
47788
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
46930
47789
  }
46931
47790
  }
@@ -46937,10 +47796,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46937
47796
  throw new Error("ONNX runtime not loaded");
46938
47797
  const onnxPath = modelOnnxPath(this.modelId);
46939
47798
  const configPath2 = modelConfigPath(this.modelId);
46940
- if (!existsSync41(onnxPath) || !existsSync41(configPath2)) {
47799
+ if (!existsSync42(onnxPath) || !existsSync42(configPath2)) {
46941
47800
  throw new Error(`Model files not found for ${this.modelId}`);
46942
47801
  }
46943
- this.config = JSON.parse(readFileSync30(configPath2, "utf8"));
47802
+ this.config = JSON.parse(readFileSync31(configPath2, "utf8"));
46944
47803
  this.session = await this.ort.InferenceSession.create(onnxPath, {
46945
47804
  executionProviders: ["cpu"],
46946
47805
  graphOptimizationLevel: "all"
@@ -46967,8 +47826,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
46967
47826
  // packages/cli/dist/tui/commands.js
46968
47827
  import * as nodeOs from "node:os";
46969
47828
  import { execSync as nodeExecSync } from "node:child_process";
46970
- import { existsSync as existsSync42, readFileSync as readFileSync31, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
46971
- import { join as join58 } from "node:path";
47829
+ import { existsSync as existsSync43, readFileSync as readFileSync32, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync13, statSync as statSync14, rmSync } from "node:fs";
47830
+ import { join as join59 } from "node:path";
46972
47831
  function safeLog(text) {
46973
47832
  if (isNeovimActive()) {
46974
47833
  writeToNeovimOutput(text + "\n");
@@ -47387,9 +48246,9 @@ async function handleSlashCommand(input, ctx) {
47387
48246
  renderInfo("No wallet configured. Ask the agent to create one via the nexus tool.");
47388
48247
  }
47389
48248
  } else if (sub === "name") {
47390
- const { homedir: homedir20 } = __require("node:os");
48249
+ const { homedir: homedir21 } = __require("node:os");
47391
48250
  const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
47392
- const namePath = __require("node:path").join(homedir20(), ".open-agents", "agent-name");
48251
+ const namePath = __require("node:path").join(homedir21(), ".open-agents", "agent-name");
47393
48252
  if (rest2) {
47394
48253
  const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
47395
48254
  if (!customName) {
@@ -47662,22 +48521,22 @@ async function handleSlashCommand(input, ctx) {
47662
48521
  let content = "";
47663
48522
  let metadata = {};
47664
48523
  if (shareType === "tool") {
47665
- const toolDir = join58(ctx.repoRoot, ".oa", "tools");
47666
- const toolFile = join58(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
47667
- if (!existsSync42(toolFile)) {
48524
+ const toolDir = join59(ctx.repoRoot, ".oa", "tools");
48525
+ const toolFile = join59(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
48526
+ if (!existsSync43(toolFile)) {
47668
48527
  renderWarning(`Tool not found: ${toolFile}`);
47669
48528
  return "handled";
47670
48529
  }
47671
- content = readFileSync31(toolFile, "utf8");
48530
+ content = readFileSync32(toolFile, "utf8");
47672
48531
  metadata = { type: "tool", name: shareName };
47673
48532
  } else if (shareType === "skill") {
47674
- const skillDir = join58(ctx.repoRoot, ".oa", "skills", shareName);
47675
- const skillFile = join58(skillDir, "SKILL.md");
47676
- if (!existsSync42(skillFile)) {
48533
+ const skillDir = join59(ctx.repoRoot, ".oa", "skills", shareName);
48534
+ const skillFile = join59(skillDir, "SKILL.md");
48535
+ if (!existsSync43(skillFile)) {
47677
48536
  renderWarning(`Skill not found: ${skillFile}`);
47678
48537
  return "handled";
47679
48538
  }
47680
- content = readFileSync31(skillFile, "utf8");
48539
+ content = readFileSync32(skillFile, "utf8");
47681
48540
  metadata = { type: "skill", name: shareName };
47682
48541
  } else {
47683
48542
  renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
@@ -47714,9 +48573,9 @@ async function handleSlashCommand(input, ctx) {
47714
48573
  try {
47715
48574
  const nexus = new NexusTool(ctx.repoRoot);
47716
48575
  await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
47717
- const regFile = join58(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
47718
- if (existsSync42(regFile)) {
47719
- const reg = JSON.parse(readFileSync31(regFile, "utf8"));
48576
+ const regFile = join59(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
48577
+ if (existsSync43(regFile)) {
48578
+ const reg = JSON.parse(readFileSync32(regFile, "utf8"));
47720
48579
  const pinned = Object.values(reg).some((e) => e.cid === importCid && e.pinned);
47721
48580
  if (pinned) {
47722
48581
  renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
@@ -47768,33 +48627,33 @@ async function handleSlashCommand(input, ctx) {
47768
48627
  lines.push(`
47769
48628
  ${c2.bold("IPFS / Helia Status")}
47770
48629
  `);
47771
- const ipfsDir = join58(ctx.repoRoot, ".oa", "ipfs");
47772
- const ipfsLocalDir = join58(ipfsDir, "local");
48630
+ const ipfsDir = join59(ctx.repoRoot, ".oa", "ipfs");
48631
+ const ipfsLocalDir = join59(ipfsDir, "local");
47773
48632
  let ipfsFiles = 0;
47774
48633
  let ipfsBytes = 0;
47775
48634
  let heliaBlocks = 0;
47776
48635
  let heliaBytes = 0;
47777
48636
  try {
47778
- if (existsSync42(ipfsLocalDir)) {
47779
- const files = readdirSync12(ipfsLocalDir).filter((f) => f.endsWith(".json"));
48637
+ if (existsSync43(ipfsLocalDir)) {
48638
+ const files = readdirSync13(ipfsLocalDir).filter((f) => f.endsWith(".json"));
47780
48639
  ipfsFiles = files.length;
47781
48640
  for (const f of files) {
47782
48641
  try {
47783
- ipfsBytes += statSync14(join58(ipfsLocalDir, f)).size;
48642
+ ipfsBytes += statSync14(join59(ipfsLocalDir, f)).size;
47784
48643
  } catch {
47785
48644
  }
47786
48645
  }
47787
48646
  }
47788
- const heliaBlockDir = join58(ipfsDir, "blocks");
47789
- if (existsSync42(heliaBlockDir)) {
48647
+ const heliaBlockDir = join59(ipfsDir, "blocks");
48648
+ if (existsSync43(heliaBlockDir)) {
47790
48649
  const walkDir = (dir) => {
47791
- for (const entry of readdirSync12(dir, { withFileTypes: true })) {
48650
+ for (const entry of readdirSync13(dir, { withFileTypes: true })) {
47792
48651
  if (entry.isDirectory())
47793
- walkDir(join58(dir, entry.name));
48652
+ walkDir(join59(dir, entry.name));
47794
48653
  else {
47795
48654
  heliaBlocks++;
47796
48655
  try {
47797
- heliaBytes += statSync14(join58(dir, entry.name)).size;
48656
+ heliaBytes += statSync14(join59(dir, entry.name)).size;
47798
48657
  } catch {
47799
48658
  }
47800
48659
  }
@@ -47810,9 +48669,9 @@ async function handleSlashCommand(input, ctx) {
47810
48669
  lines.push(` Blocks: ${c2.bold(String(heliaBlocks))} Size: ${c2.bold(formatFileSize(heliaBytes))}`);
47811
48670
  lines.push(` Backend: ${heliaBlocks > 0 ? c2.green("helia-ipfs") : c2.yellow("sha256-local (Helia not initialized)")}`);
47812
48671
  try {
47813
- const statusFile = join58(ctx.repoRoot, ".oa", "nexus", "status.json");
47814
- if (existsSync42(statusFile)) {
47815
- const status = JSON.parse(readFileSync31(statusFile, "utf8"));
48672
+ const statusFile = join59(ctx.repoRoot, ".oa", "nexus", "status.json");
48673
+ if (existsSync43(statusFile)) {
48674
+ const status = JSON.parse(readFileSync32(statusFile, "utf8"));
47816
48675
  if (status.peerId) {
47817
48676
  lines.push(`
47818
48677
  ${c2.bold("Peer Info")}`);
@@ -47831,11 +48690,11 @@ async function handleSlashCommand(input, ctx) {
47831
48690
  ${c2.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
47832
48691
  lines.push(`
47833
48692
  ${c2.bold("Identity Kernel")}`);
47834
- const idDir = join58(ctx.repoRoot, ".oa", "identity");
48693
+ const idDir = join59(ctx.repoRoot, ".oa", "identity");
47835
48694
  try {
47836
- const stateFile = join58(idDir, "self-state.json");
47837
- if (existsSync42(stateFile)) {
47838
- const state = JSON.parse(readFileSync31(stateFile, "utf8"));
48695
+ const stateFile = join59(idDir, "self-state.json");
48696
+ if (existsSync43(stateFile)) {
48697
+ const state = JSON.parse(readFileSync32(stateFile, "utf8"));
47839
48698
  lines.push(` Version: ${c2.bold("v" + (state.version ?? "?"))} Sessions: ${c2.bold(String(state.session_count ?? 0))}`);
47840
48699
  if (state.narrative_summary) {
47841
48700
  lines.push(` Narrative: ${c2.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
@@ -47844,9 +48703,9 @@ async function handleSlashCommand(input, ctx) {
47844
48703
  const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
47845
48704
  lines.push(` Traits: ${c2.dim(traits.slice(0, 60))}`);
47846
48705
  }
47847
- const cidFile = join58(idDir, "cids.json");
47848
- if (existsSync42(cidFile)) {
47849
- const cids = JSON.parse(readFileSync31(cidFile, "utf8"));
48706
+ const cidFile = join59(idDir, "cids.json");
48707
+ if (existsSync43(cidFile)) {
48708
+ const cids = JSON.parse(readFileSync32(cidFile, "utf8"));
47850
48709
  const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
47851
48710
  if (lastCid)
47852
48711
  lines.push(` Last CID: ${c2.dim(String(lastCid).slice(0, 50))}`);
@@ -47859,9 +48718,9 @@ async function handleSlashCommand(input, ctx) {
47859
48718
  lines.push(`
47860
48719
  ${c2.bold("Memory Sentiment")}`);
47861
48720
  try {
47862
- const metaFile = join58(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
47863
- if (existsSync42(metaFile)) {
47864
- const store = JSON.parse(readFileSync31(metaFile, "utf8"));
48721
+ const metaFile = join59(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
48722
+ if (existsSync43(metaFile)) {
48723
+ const store = JSON.parse(readFileSync32(metaFile, "utf8"));
47865
48724
  const active = store.filter((m) => m.type !== "quarantine");
47866
48725
  const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
47867
48726
  const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
@@ -47879,8 +48738,8 @@ async function handleSlashCommand(input, ctx) {
47879
48738
  } catch {
47880
48739
  }
47881
48740
  try {
47882
- const dbPath = join58(ctx.repoRoot, ".oa", "memory", "structured.db");
47883
- if (existsSync42(dbPath)) {
48741
+ const dbPath = join59(ctx.repoRoot, ".oa", "memory", "structured.db");
48742
+ if (existsSync43(dbPath)) {
47884
48743
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
47885
48744
  const db = initDb2(dbPath);
47886
48745
  const memStore = new ProceduralMemoryStore2(db);
@@ -47901,8 +48760,8 @@ async function handleSlashCommand(input, ctx) {
47901
48760
  lines.push(`
47902
48761
  ${c2.bold("Storage Overview")}
47903
48762
  `);
47904
- const oaDir = join58(ctx.repoRoot, ".oa");
47905
- if (!existsSync42(oaDir)) {
48763
+ const oaDir = join59(ctx.repoRoot, ".oa");
48764
+ if (!existsSync43(oaDir)) {
47906
48765
  lines.push(` ${c2.dim("No .oa/ directory found.")}`);
47907
48766
  safeLog(lines.join("\n") + "\n");
47908
48767
  return "handled";
@@ -47911,8 +48770,8 @@ async function handleSlashCommand(input, ctx) {
47911
48770
  const categories = {};
47912
48771
  const walkStorage = (dir, category) => {
47913
48772
  try {
47914
- for (const entry of readdirSync12(dir, { withFileTypes: true })) {
47915
- const full = join58(dir, entry.name);
48773
+ for (const entry of readdirSync13(dir, { withFileTypes: true })) {
48774
+ const full = join59(dir, entry.name);
47916
48775
  if (entry.isDirectory()) {
47917
48776
  const subCat = category || entry.name;
47918
48777
  walkStorage(full, subCat);
@@ -47945,13 +48804,13 @@ async function handleSlashCommand(input, ctx) {
47945
48804
  const sensitiveFound = [];
47946
48805
  const checkSensitive = (dir) => {
47947
48806
  try {
47948
- for (const entry of readdirSync12(dir, { withFileTypes: true })) {
48807
+ for (const entry of readdirSync13(dir, { withFileTypes: true })) {
47949
48808
  const name = entry.name.toLowerCase();
47950
48809
  if (sensitivePatterns.some((p) => name.includes(p))) {
47951
- sensitiveFound.push(join58(dir, entry.name).replace(oaDir + "/", ""));
48810
+ sensitiveFound.push(join59(dir, entry.name).replace(oaDir + "/", ""));
47952
48811
  }
47953
48812
  if (entry.isDirectory())
47954
- checkSensitive(join58(dir, entry.name));
48813
+ checkSensitive(join59(dir, entry.name));
47955
48814
  }
47956
48815
  } catch {
47957
48816
  }
@@ -47979,8 +48838,8 @@ async function handleSlashCommand(input, ctx) {
47979
48838
  renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
47980
48839
  return "handled";
47981
48840
  }
47982
- const resolvedPath = join58(ctx.repoRoot, filePath);
47983
- if (!existsSync42(resolvedPath)) {
48841
+ const resolvedPath = join59(ctx.repoRoot, filePath);
48842
+ if (!existsSync43(resolvedPath)) {
47984
48843
  renderWarning(`File not found: ${resolvedPath}`);
47985
48844
  return "handled";
47986
48845
  }
@@ -47996,9 +48855,9 @@ async function handleSlashCommand(input, ctx) {
47996
48855
  }
47997
48856
  try {
47998
48857
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
47999
- const dbDir = join58(ctx.repoRoot, ".oa", "memory");
48000
- mkdirSync18(dbDir, { recursive: true });
48001
- const db = initDb2(join58(dbDir, "structured.db"));
48858
+ const dbDir = join59(ctx.repoRoot, ".oa", "memory");
48859
+ mkdirSync19(dbDir, { recursive: true });
48860
+ const db = initDb2(join59(dbDir, "structured.db"));
48002
48861
  const memStore = new ProceduralMemoryStore2(db);
48003
48862
  if (isAudio) {
48004
48863
  renderInfo(`Transcribing: ${filePath}...`);
@@ -48039,7 +48898,7 @@ async function handleSlashCommand(input, ctx) {
48039
48898
  return "handled";
48040
48899
  }
48041
48900
  } else {
48042
- content = readFileSync31(resolvedPath, "utf8");
48901
+ content = readFileSync32(resolvedPath, "utf8");
48043
48902
  }
48044
48903
  if (!content.trim()) {
48045
48904
  renderWarning("No content extracted.");
@@ -48078,9 +48937,9 @@ async function handleSlashCommand(input, ctx) {
48078
48937
  }
48079
48938
  case "fortemi": {
48080
48939
  const fortemiSubCmd = (arg || "").trim().toLowerCase();
48081
- const fortemiDir = join58(ctx.repoRoot, "..", "fortemi-react");
48082
- const altFortemiDir = join58(nodeOs.homedir(), "fortemi-react");
48083
- const fDir = existsSync42(fortemiDir) ? fortemiDir : existsSync42(altFortemiDir) ? altFortemiDir : null;
48940
+ const fortemiDir = join59(ctx.repoRoot, "..", "fortemi-react");
48941
+ const altFortemiDir = join59(nodeOs.homedir(), "fortemi-react");
48942
+ const fDir = existsSync43(fortemiDir) ? fortemiDir : existsSync43(altFortemiDir) ? altFortemiDir : null;
48084
48943
  if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
48085
48944
  if (!fDir) {
48086
48945
  renderWarning("fortemi-react not found adjacent or in home directory.");
@@ -48095,14 +48954,14 @@ async function handleSlashCommand(input, ctx) {
48095
48954
  // 24h
48096
48955
  nonce: Math.random().toString(36).slice(2, 10)
48097
48956
  };
48098
- const jwtFile = join58(ctx.repoRoot, ".oa", "fortemi-jwt.json");
48099
- mkdirSync18(join58(ctx.repoRoot, ".oa"), { recursive: true });
48100
- writeFileSync19(jwtFile, JSON.stringify(jwtPayload, null, 2));
48957
+ const jwtFile = join59(ctx.repoRoot, ".oa", "fortemi-jwt.json");
48958
+ mkdirSync19(join59(ctx.repoRoot, ".oa"), { recursive: true });
48959
+ writeFileSync20(jwtFile, JSON.stringify(jwtPayload, null, 2));
48101
48960
  renderInfo(`Launching fortemi-react from ${fDir}...`);
48102
48961
  try {
48103
- const { spawn: spawn22 } = __require("node:child_process");
48104
- const child = spawn22("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
48105
- cwd: join58(fDir, "apps", "standalone"),
48962
+ const { spawn: spawn23 } = __require("node:child_process");
48963
+ const child = spawn23("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
48964
+ cwd: join59(fDir, "apps", "standalone"),
48106
48965
  stdio: "ignore",
48107
48966
  detached: true,
48108
48967
  env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
@@ -48111,8 +48970,8 @@ async function handleSlashCommand(input, ctx) {
48111
48970
  renderInfo("Fortemi-React starting on http://localhost:3000");
48112
48971
  renderInfo(`JWT saved to ${jwtFile}`);
48113
48972
  renderInfo("Memory operations will proxy to fortemi when available.");
48114
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48115
- writeFileSync19(bridgeFile, JSON.stringify({
48973
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48974
+ writeFileSync20(bridgeFile, JSON.stringify({
48116
48975
  url: "http://localhost:3000",
48117
48976
  pid: child.pid,
48118
48977
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -48124,12 +48983,12 @@ async function handleSlashCommand(input, ctx) {
48124
48983
  return "handled";
48125
48984
  }
48126
48985
  if (fortemiSubCmd === "status") {
48127
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48128
- if (!existsSync42(bridgeFile)) {
48986
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48987
+ if (!existsSync43(bridgeFile)) {
48129
48988
  renderInfo("Fortemi bridge: not connected. Run /fortemi start");
48130
48989
  return "handled";
48131
48990
  }
48132
- const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
48991
+ const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
48133
48992
  let alive = false;
48134
48993
  try {
48135
48994
  process.kill(bridge.pid, 0);
@@ -48149,15 +49008,15 @@ async function handleSlashCommand(input, ctx) {
48149
49008
  lines.push(` Process: ${alive ? c2.green("running") : c2.yellow("not running")} (PID ${bridge.pid})`);
48150
49009
  lines.push(` HTTP: ${httpOk ? c2.green("connected") : c2.yellow("unreachable")}`);
48151
49010
  lines.push(` Started: ${bridge.startedAt}`);
48152
- lines.push(` JWT: ${existsSync42(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
49011
+ lines.push(` JWT: ${existsSync43(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
48153
49012
  lines.push("");
48154
49013
  safeLog(lines.join("\n"));
48155
49014
  return "handled";
48156
49015
  }
48157
49016
  if (fortemiSubCmd === "stop") {
48158
- const bridgeFile = join58(ctx.repoRoot, ".oa", "fortemi-bridge.json");
48159
- if (existsSync42(bridgeFile)) {
48160
- const bridge = JSON.parse(readFileSync31(bridgeFile, "utf8"));
49017
+ const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
49018
+ if (existsSync43(bridgeFile)) {
49019
+ const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
48161
49020
  try {
48162
49021
  process.kill(bridge.pid, "SIGTERM");
48163
49022
  } catch {
@@ -48214,6 +49073,76 @@ async function handleSlashCommand(input, ctx) {
48214
49073
  ctx.saveSettings(settings);
48215
49074
  };
48216
49075
  if (arg) {
49076
+ if (arg === "personaplex" || arg === "pp") {
49077
+ const { detectPersonaPlexCapability: detectPersonaPlexCapability2, isPersonaPlexInstalled: isPersonaPlexInstalled2, installPersonaPlex: installPersonaPlex2, startPersonaPlexDaemon: startPersonaPlexDaemon2, stopPersonaPlex: stopPersonaPlex2, isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
49078
+ const caps = detectPersonaPlexCapability2();
49079
+ if (!caps.supported) {
49080
+ renderWarning(`PersonaPlex not available: ${caps.reason}`);
49081
+ renderInfo("Requirements: NVIDIA GPU with \u226516GB VRAM (RTX 3090/4090/A100+), CUDA 12.1+, PyTorch");
49082
+ return "handled";
49083
+ }
49084
+ renderInfo(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB VRAM) \u2014 PersonaPlex compatible \u2713`);
49085
+ if (!isPersonaPlexInstalled2()) {
49086
+ renderInfo("Installing PersonaPlex-7B (~14GB download)...");
49087
+ const ok = await installPersonaPlex2((msg2) => renderInfo(msg2));
49088
+ if (!ok) {
49089
+ renderError("PersonaPlex installation failed.");
49090
+ return "handled";
49091
+ }
49092
+ }
49093
+ if (isPersonaPlexRunning2()) {
49094
+ renderInfo("PersonaPlex daemon is running.");
49095
+ renderInfo("Use /call to start a full-duplex voice session.");
49096
+ } else {
49097
+ const url = await startPersonaPlexDaemon2((msg2) => renderInfo(msg2));
49098
+ if (url) {
49099
+ renderInfo(`PersonaPlex ready at ${url}`);
49100
+ renderInfo("Use /call to start a full-duplex voice session with PersonaPlex.");
49101
+ } else {
49102
+ renderError("PersonaPlex daemon failed to start.");
49103
+ }
49104
+ }
49105
+ return "handled";
49106
+ }
49107
+ if (arg.startsWith("clone")) {
49108
+ const parts = arg.slice(5).trim().split(/\s+/);
49109
+ if (parts.length < 2) {
49110
+ renderInfo("Usage: /voice clone <wav-file> <voice-name>");
49111
+ renderInfo("Example: /voice clone ~/my_voice.wav MyVoice");
49112
+ renderInfo("");
49113
+ renderInfo("Record 4-10 seconds of clean speech (24kHz mono WAV recommended).");
49114
+ renderInfo("The voice embedding will be extracted and saved for PersonaPlex.");
49115
+ return "handled";
49116
+ }
49117
+ const [wavPath, voiceName] = parts;
49118
+ const { clonePersonaPlexVoice: clonePersonaPlexVoice2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
49119
+ const result = await clonePersonaPlexVoice2(wavPath, voiceName, (msg2) => renderInfo(msg2));
49120
+ if (result) {
49121
+ renderInfo(`Use with /call by setting voice_prompt to "${voiceName}.pt"`);
49122
+ }
49123
+ return "handled";
49124
+ }
49125
+ if (arg === "list" || arg === "voices") {
49126
+ const { listPersonaPlexVoices: listPersonaPlexVoices2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
49127
+ const voices = listPersonaPlexVoices2();
49128
+ const builtins = voices.filter((v) => v.type === "builtin");
49129
+ const customs = voices.filter((v) => v.type === "custom");
49130
+ renderInfo("Natural voices:");
49131
+ renderInfo(" Female: " + builtins.filter((v) => v.name.startsWith("NATF")).map((v) => v.name).join(", "));
49132
+ renderInfo(" Male: " + builtins.filter((v) => v.name.startsWith("NATM")).map((v) => v.name).join(", "));
49133
+ renderInfo("Variety voices:");
49134
+ renderInfo(" Female: " + builtins.filter((v) => v.name.startsWith("VARF")).map((v) => v.name).join(", "));
49135
+ renderInfo(" Male: " + builtins.filter((v) => v.name.startsWith("VARM")).map((v) => v.name).join(", "));
49136
+ if (customs.length > 0) {
49137
+ renderInfo("Custom cloned voices:");
49138
+ for (const v of customs) {
49139
+ renderInfo(` ${v.name} (${v.path})`);
49140
+ }
49141
+ } else {
49142
+ renderInfo("No custom voices. Use /voice clone <wav> <name> to create one.");
49143
+ }
49144
+ return "handled";
49145
+ }
48217
49146
  if (arg === "enable" || arg === "on") {
48218
49147
  const msg2 = await ctx.voiceToggle();
48219
49148
  const isOn = msg2.toLowerCase().includes("enabled") || msg2.toLowerCase().includes("on");
@@ -48738,10 +49667,10 @@ async function handleSlashCommand(input, ctx) {
48738
49667
  let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
48739
49668
  if (!sponsorName || sponsorName.length < 2) {
48740
49669
  try {
48741
- const { homedir: homedir20 } = __require("os");
48742
- const namePath = __require("path").join(homedir20(), ".open-agents", "agent-name");
48743
- if (existsSync42(namePath))
48744
- sponsorName = readFileSync31(namePath, "utf8").trim();
49670
+ const { homedir: homedir21 } = __require("os");
49671
+ const namePath = __require("path").join(homedir21(), ".open-agents", "agent-name");
49672
+ if (existsSync43(namePath))
49673
+ sponsorName = readFileSync32(namePath, "utf8").trim();
48745
49674
  } catch {
48746
49675
  }
48747
49676
  if (!sponsorName)
@@ -49812,13 +50741,13 @@ async function showCohereDashboard(ctx) {
49812
50741
  } else if (idResult.key === "view") {
49813
50742
  await ik.execute({ operation: "hydrate" });
49814
50743
  } else if (idResult.key === "history") {
49815
- const snapDir = join58(ctx.repoRoot, ".oa", "identity", "snapshots");
49816
- if (existsSync42(snapDir)) {
49817
- const snaps = readdirSync12(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
50744
+ const snapDir = join59(ctx.repoRoot, ".oa", "identity", "snapshots");
50745
+ if (existsSync43(snapDir)) {
50746
+ const snaps = readdirSync13(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
49818
50747
  const snapItems = snaps.slice(0, 20).map((f) => ({
49819
50748
  key: f,
49820
50749
  label: f.replace(".json", ""),
49821
- detail: `${formatFileSize(statSync14(join58(snapDir, f)).size)}`
50750
+ detail: `${formatFileSize(statSync14(join59(snapDir, f)).size)}`
49822
50751
  }));
49823
50752
  if (snapItems.length > 0) {
49824
50753
  await tuiSelect({
@@ -50139,14 +51068,14 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
50139
51068
  continue;
50140
51069
  }
50141
51070
  const { basename: basename18, join: pathJoin } = await import("node:path");
50142
- const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync30, existsSync: exists } = await import("node:fs");
50143
- const { homedir: homedir20 } = await import("node:os");
51071
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync31, existsSync: exists } = await import("node:fs");
51072
+ const { homedir: homedir21 } = await import("node:os");
50144
51073
  const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
50145
- const destDir = pathJoin(homedir20(), ".open-agents", "voice", "models", modelName);
51074
+ const destDir = pathJoin(homedir21(), ".open-agents", "voice", "models", modelName);
50146
51075
  if (!exists(destDir))
50147
- mkdirSync30(destDir, { recursive: true });
50148
- copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
50149
- copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
51076
+ mkdirSync31(destDir, { recursive: true });
51077
+ copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
51078
+ copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
50150
51079
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
50151
51080
  registerCustomOnnxModel2(modelName, modelName);
50152
51081
  await ctx.voiceSetModel(modelName);
@@ -50272,8 +51201,8 @@ async function handleVoiceList(ctx, focusFilename) {
50272
51201
  helpers.getInput("Export to:", defaultPath).then((destPath) => {
50273
51202
  if (destPath !== null && destPath.trim()) {
50274
51203
  try {
50275
- const { copyFileSync: copyFileSync2 } = __require("node:fs");
50276
- copyFileSync2(clone.path, destPath.trim());
51204
+ const { copyFileSync: copyFileSync3 } = __require("node:fs");
51205
+ copyFileSync3(clone.path, destPath.trim());
50277
51206
  renderInfo(`Exported "${clone.name}" \u2192 ${destPath.trim()}`);
50278
51207
  } catch (err) {
50279
51208
  renderError(`Export failed: ${err.message}`);
@@ -50771,11 +51700,11 @@ async function handleSponsoredEndpoint(ctx, local) {
50771
51700
  }
50772
51701
  } catch {
50773
51702
  }
50774
- const sponsorDir2 = join58(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
50775
- const knownFile = join58(sponsorDir2, "known-sponsors.json");
51703
+ const sponsorDir2 = join59(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
51704
+ const knownFile = join59(sponsorDir2, "known-sponsors.json");
50776
51705
  try {
50777
- if (existsSync42(knownFile)) {
50778
- const saved = JSON.parse(readFileSync31(knownFile, "utf8"));
51706
+ if (existsSync43(knownFile)) {
51707
+ const saved = JSON.parse(readFileSync32(knownFile, "utf8"));
50779
51708
  for (const s of saved) {
50780
51709
  if (!sponsors.some((sp) => sp.url === s.url)) {
50781
51710
  sponsors.push({ ...s, source: "saved" });
@@ -50910,11 +51839,11 @@ async function handleSponsoredEndpoint(ctx, local) {
50910
51839
  }
50911
51840
  const saveKey = selected.url || selected.peerId || selected.name;
50912
51841
  try {
50913
- mkdirSync18(sponsorDir2, { recursive: true });
50914
- const existing = existsSync42(knownFile) ? JSON.parse(readFileSync31(knownFile, "utf8")) : [];
51842
+ mkdirSync19(sponsorDir2, { recursive: true });
51843
+ const existing = existsSync43(knownFile) ? JSON.parse(readFileSync32(knownFile, "utf8")) : [];
50915
51844
  const updated = existing.filter((s) => (s.url || s.peerId || s.name) !== saveKey);
50916
51845
  updated.push(selected);
50917
- writeFileSync19(knownFile, JSON.stringify(updated, null, 2), "utf8");
51846
+ writeFileSync20(knownFile, JSON.stringify(updated, null, 2), "utf8");
50918
51847
  } catch {
50919
51848
  }
50920
51849
  renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
@@ -50983,11 +51912,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
50983
51912
  const models = await fetchModels(peerUrl, authKey);
50984
51913
  if (models.length > 0) {
50985
51914
  try {
50986
- const { writeFileSync: writeFileSync29, mkdirSync: mkdirSync30 } = await import("node:fs");
50987
- const { join: join76, dirname: dirname23 } = await import("node:path");
50988
- const cachePath = join76(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
50989
- mkdirSync30(dirname23(cachePath), { recursive: true });
50990
- writeFileSync29(cachePath, JSON.stringify({
51915
+ const { writeFileSync: writeFileSync30, mkdirSync: mkdirSync31 } = await import("node:fs");
51916
+ const { join: join77, dirname: dirname24 } = await import("node:path");
51917
+ const cachePath = join77(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
51918
+ mkdirSync31(dirname24(cachePath), { recursive: true });
51919
+ writeFileSync30(cachePath, JSON.stringify({
50991
51920
  peerId,
50992
51921
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
50993
51922
  models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
@@ -51036,7 +51965,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
51036
51965
  }
51037
51966
  }
51038
51967
  async function handleParallel(arg, ctx) {
51039
- const { execSync: execSync34 } = await import("node:child_process");
51968
+ const { execSync: execSync35 } = await import("node:child_process");
51040
51969
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
51041
51970
  const isRemote = ctx.config.backendType === "nexus";
51042
51971
  if (isRemote) {
@@ -51060,7 +51989,7 @@ async function handleParallel(arg, ctx) {
51060
51989
  }
51061
51990
  let systemdVal = "";
51062
51991
  try {
51063
- const out = execSync34("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
51992
+ const out = execSync35("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
51064
51993
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
51065
51994
  if (match)
51066
51995
  systemdVal = match[1];
@@ -51089,7 +52018,7 @@ async function handleParallel(arg, ctx) {
51089
52018
  }
51090
52019
  const isSystemd = (() => {
51091
52020
  try {
51092
- const out = execSync34("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
52021
+ const out = execSync35("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
51093
52022
  return out === "active" || out === "inactive";
51094
52023
  } catch {
51095
52024
  return false;
@@ -51103,10 +52032,10 @@ async function handleParallel(arg, ctx) {
51103
52032
  const overrideContent = `[Service]
51104
52033
  Environment="OLLAMA_NUM_PARALLEL=${n}"
51105
52034
  `;
51106
- execSync34(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
51107
- execSync34(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
51108
- execSync34("sudo systemctl daemon-reload", { stdio: "pipe" });
51109
- execSync34("sudo systemctl restart ollama.service", { stdio: "pipe" });
52035
+ execSync35(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
52036
+ execSync35(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
52037
+ execSync35("sudo systemctl daemon-reload", { stdio: "pipe" });
52038
+ execSync35("sudo systemctl restart ollama.service", { stdio: "pipe" });
51110
52039
  let ready = false;
51111
52040
  for (let i = 0; i < 30 && !ready; i++) {
51112
52041
  await new Promise((r) => setTimeout(r, 500));
@@ -51133,13 +52062,13 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
51133
52062
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
51134
52063
  try {
51135
52064
  try {
51136
- execSync34("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
52065
+ execSync35("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
51137
52066
  } catch {
51138
52067
  }
51139
52068
  await new Promise((r) => setTimeout(r, 1e3));
51140
52069
  process.env.OLLAMA_NUM_PARALLEL = String(n);
51141
- const { spawn: spawn22 } = await import("node:child_process");
51142
- const child = spawn22("ollama", ["serve"], {
52070
+ const { spawn: spawn23 } = await import("node:child_process");
52071
+ const child = spawn23("ollama", ["serve"], {
51143
52072
  stdio: "ignore",
51144
52073
  detached: true,
51145
52074
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
@@ -51185,18 +52114,18 @@ async function handleUpdate(subcommand, ctx) {
51185
52114
  let currentVersion = "0.0.0";
51186
52115
  try {
51187
52116
  const { createRequire: createRequire6 } = await import("node:module");
51188
- const { fileURLToPath: fileURLToPath15 } = await import("node:url");
51189
- const { dirname: dirname23, join: join76 } = await import("node:path");
51190
- const { existsSync: existsSync56 } = await import("node:fs");
52117
+ const { fileURLToPath: fileURLToPath16 } = await import("node:url");
52118
+ const { dirname: dirname24, join: join77 } = await import("node:path");
52119
+ const { existsSync: existsSync57 } = await import("node:fs");
51191
52120
  const req = createRequire6(import.meta.url);
51192
- const thisDir = dirname23(fileURLToPath15(import.meta.url));
52121
+ const thisDir = dirname24(fileURLToPath16(import.meta.url));
51193
52122
  const candidates = [
51194
- join76(thisDir, "..", "package.json"),
51195
- join76(thisDir, "..", "..", "package.json"),
51196
- join76(thisDir, "..", "..", "..", "package.json")
52123
+ join77(thisDir, "..", "package.json"),
52124
+ join77(thisDir, "..", "..", "package.json"),
52125
+ join77(thisDir, "..", "..", "..", "package.json")
51197
52126
  ];
51198
52127
  for (const pkgPath of candidates) {
51199
- if (existsSync56(pkgPath)) {
52128
+ if (existsSync57(pkgPath)) {
51200
52129
  const pkg = req(pkgPath);
51201
52130
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
51202
52131
  currentVersion = pkg.version ?? "0.0.0";
@@ -51952,18 +52881,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
51952
52881
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
51953
52882
  let copied = false;
51954
52883
  try {
51955
- const { execSync: execSync34 } = __require("node:child_process");
52884
+ const { execSync: execSync35 } = __require("node:child_process");
51956
52885
  const platform6 = process.platform;
51957
52886
  if (platform6 === "darwin") {
51958
- execSync34("pbcopy", { input: cmd, timeout: 3e3 });
52887
+ execSync35("pbcopy", { input: cmd, timeout: 3e3 });
51959
52888
  copied = true;
51960
52889
  } else if (platform6 === "win32") {
51961
- execSync34("clip", { input: cmd, timeout: 3e3 });
52890
+ execSync35("clip", { input: cmd, timeout: 3e3 });
51962
52891
  copied = true;
51963
52892
  } else {
51964
52893
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
51965
52894
  try {
51966
- execSync34(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
52895
+ execSync35(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
51967
52896
  copied = true;
51968
52897
  break;
51969
52898
  } catch {
@@ -52050,10 +52979,10 @@ var init_commands = __esm({
52050
52979
  });
52051
52980
 
52052
52981
  // packages/cli/dist/tui/project-context.js
52053
- import { existsSync as existsSync43, readFileSync as readFileSync32, readdirSync as readdirSync13 } from "node:fs";
52054
- import { join as join59, basename as basename12 } from "node:path";
52055
- import { execSync as execSync30 } from "node:child_process";
52056
- import { homedir as homedir16, platform as platform4, release } from "node:os";
52982
+ import { existsSync as existsSync44, readFileSync as readFileSync33, readdirSync as readdirSync14 } from "node:fs";
52983
+ import { join as join60, basename as basename12 } from "node:path";
52984
+ import { execSync as execSync31 } from "node:child_process";
52985
+ import { homedir as homedir17, platform as platform4, release } from "node:os";
52057
52986
  function getModelTier(modelName) {
52058
52987
  const m = modelName.toLowerCase();
52059
52988
  const sizeMatch = m.match(/\b(\d+)b\b/);
@@ -52086,10 +53015,10 @@ function loadProjectMap(repoRoot) {
52086
53015
  if (!hasOaDirectory(repoRoot)) {
52087
53016
  initOaDirectory(repoRoot);
52088
53017
  }
52089
- const mapPath2 = join59(repoRoot, OA_DIR, "context", "project-map.md");
52090
- if (existsSync43(mapPath2)) {
53018
+ const mapPath2 = join60(repoRoot, OA_DIR, "context", "project-map.md");
53019
+ if (existsSync44(mapPath2)) {
52091
53020
  try {
52092
- const content = readFileSync32(mapPath2, "utf-8");
53021
+ const content = readFileSync33(mapPath2, "utf-8");
52093
53022
  return content;
52094
53023
  } catch {
52095
53024
  }
@@ -52098,19 +53027,19 @@ function loadProjectMap(repoRoot) {
52098
53027
  }
52099
53028
  function getGitInfo(repoRoot) {
52100
53029
  try {
52101
- execSync30("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
53030
+ execSync31("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
52102
53031
  } catch {
52103
53032
  return "";
52104
53033
  }
52105
53034
  const lines = [];
52106
53035
  try {
52107
- const branch = execSync30("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
53036
+ const branch = execSync31("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52108
53037
  if (branch)
52109
53038
  lines.push(`Branch: ${branch}`);
52110
53039
  } catch {
52111
53040
  }
52112
53041
  try {
52113
- const status = execSync30("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
53042
+ const status = execSync31("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52114
53043
  if (status) {
52115
53044
  const changed = status.split("\n").length;
52116
53045
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -52120,7 +53049,7 @@ function getGitInfo(repoRoot) {
52120
53049
  } catch {
52121
53050
  }
52122
53051
  try {
52123
- const log = execSync30("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
53052
+ const log = execSync31("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
52124
53053
  if (log)
52125
53054
  lines.push(`Recent commits:
52126
53055
  ${log}`);
@@ -52130,31 +53059,31 @@ ${log}`);
52130
53059
  }
52131
53060
  function loadMemoryContext(repoRoot) {
52132
53061
  const sections = [];
52133
- const oaMemDir = join59(repoRoot, OA_DIR, "memory");
53062
+ const oaMemDir = join60(repoRoot, OA_DIR, "memory");
52134
53063
  const oaEntries = loadMemoryDir(oaMemDir, "project");
52135
53064
  if (oaEntries)
52136
53065
  sections.push(oaEntries);
52137
- const legacyMemDir = join59(repoRoot, ".open-agents", "memory");
52138
- if (legacyMemDir !== oaMemDir && existsSync43(legacyMemDir)) {
53066
+ const legacyMemDir = join60(repoRoot, ".open-agents", "memory");
53067
+ if (legacyMemDir !== oaMemDir && existsSync44(legacyMemDir)) {
52139
53068
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
52140
53069
  if (legacyEntries)
52141
53070
  sections.push(legacyEntries);
52142
53071
  }
52143
- const globalMemDir = join59(homedir16(), ".open-agents", "memory");
53072
+ const globalMemDir = join60(homedir17(), ".open-agents", "memory");
52144
53073
  const globalEntries = loadMemoryDir(globalMemDir, "global");
52145
53074
  if (globalEntries)
52146
53075
  sections.push(globalEntries);
52147
53076
  return sections.join("\n\n");
52148
53077
  }
52149
53078
  function loadMemoryDir(memDir, scope) {
52150
- if (!existsSync43(memDir))
53079
+ if (!existsSync44(memDir))
52151
53080
  return "";
52152
53081
  const lines = [];
52153
53082
  try {
52154
- const files = readdirSync13(memDir).filter((f) => f.endsWith(".json"));
53083
+ const files = readdirSync14(memDir).filter((f) => f.endsWith(".json"));
52155
53084
  for (const file of files.slice(0, 10)) {
52156
53085
  try {
52157
- const raw = readFileSync32(join59(memDir, file), "utf-8");
53086
+ const raw = readFileSync33(join60(memDir, file), "utf-8");
52158
53087
  const entries = JSON.parse(raw);
52159
53088
  const topic = basename12(file, ".json");
52160
53089
  const keys = Object.keys(entries);
@@ -53294,8 +54223,8 @@ __export(banner_exports, {
53294
54223
  saveBannerDesign: () => saveBannerDesign,
53295
54224
  setGridText: () => setGridText
53296
54225
  });
53297
- import { existsSync as existsSync44, readFileSync as readFileSync33, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19 } from "node:fs";
53298
- import { join as join60 } from "node:path";
54226
+ import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20 } from "node:fs";
54227
+ import { join as join61 } from "node:path";
53299
54228
  function generateMnemonic(seed) {
53300
54229
  let h = 2166136261;
53301
54230
  for (let i = 0; i < seed.length; i++) {
@@ -53490,27 +54419,27 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
53490
54419
  };
53491
54420
  }
53492
54421
  function saveBannerDesign(workDir, design) {
53493
- const dir = join60(workDir, ".oa", "banners");
53494
- mkdirSync19(dir, { recursive: true });
53495
- writeFileSync20(join60(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
54422
+ const dir = join61(workDir, ".oa", "banners");
54423
+ mkdirSync20(dir, { recursive: true });
54424
+ writeFileSync21(join61(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
53496
54425
  }
53497
54426
  function loadBannerDesign(workDir, id) {
53498
- const file = join60(workDir, ".oa", "banners", `${id}.json`);
53499
- if (!existsSync44(file))
54427
+ const file = join61(workDir, ".oa", "banners", `${id}.json`);
54428
+ if (!existsSync45(file))
53500
54429
  return null;
53501
54430
  try {
53502
- return JSON.parse(readFileSync33(file, "utf8"));
54431
+ return JSON.parse(readFileSync34(file, "utf8"));
53503
54432
  } catch {
53504
54433
  return null;
53505
54434
  }
53506
54435
  }
53507
54436
  function listBannerDesigns(workDir) {
53508
- const dir = join60(workDir, ".oa", "banners");
53509
- if (!existsSync44(dir))
54437
+ const dir = join61(workDir, ".oa", "banners");
54438
+ if (!existsSync45(dir))
53510
54439
  return [];
53511
54440
  try {
53512
- const { readdirSync: readdirSync23 } = __require("node:fs");
53513
- return readdirSync23(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
54441
+ const { readdirSync: readdirSync24 } = __require("node:fs");
54442
+ return readdirSync24(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
53514
54443
  } catch {
53515
54444
  return [];
53516
54445
  }
@@ -53864,22 +54793,22 @@ var init_banner = __esm({
53864
54793
  });
53865
54794
 
53866
54795
  // packages/cli/dist/tui/carousel-descriptors.js
53867
- import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20, readdirSync as readdirSync14 } from "node:fs";
53868
- import { join as join61, basename as basename13 } from "node:path";
54796
+ import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync22, mkdirSync as mkdirSync21, readdirSync as readdirSync15 } from "node:fs";
54797
+ import { join as join62, basename as basename13 } from "node:path";
53869
54798
  function loadToolProfile(repoRoot) {
53870
- const filePath = join61(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
54799
+ const filePath = join62(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
53871
54800
  try {
53872
- if (!existsSync45(filePath))
54801
+ if (!existsSync46(filePath))
53873
54802
  return null;
53874
- return JSON.parse(readFileSync34(filePath, "utf-8"));
54803
+ return JSON.parse(readFileSync35(filePath, "utf-8"));
53875
54804
  } catch {
53876
54805
  return null;
53877
54806
  }
53878
54807
  }
53879
54808
  function saveToolProfile(repoRoot, profile) {
53880
- const contextDir = join61(repoRoot, OA_DIR, "context");
53881
- mkdirSync20(contextDir, { recursive: true });
53882
- writeFileSync21(join61(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
54809
+ const contextDir = join62(repoRoot, OA_DIR, "context");
54810
+ mkdirSync21(contextDir, { recursive: true });
54811
+ writeFileSync22(join62(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
53883
54812
  }
53884
54813
  function categorizeToolCall(toolName) {
53885
54814
  for (const cat of TOOL_CATEGORIES) {
@@ -53937,25 +54866,25 @@ function weightedColor(profile) {
53937
54866
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
53938
54867
  }
53939
54868
  function loadCachedDescriptors(repoRoot) {
53940
- const filePath = join61(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
54869
+ const filePath = join62(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
53941
54870
  try {
53942
- if (!existsSync45(filePath))
54871
+ if (!existsSync46(filePath))
53943
54872
  return null;
53944
- const cached = JSON.parse(readFileSync34(filePath, "utf-8"));
54873
+ const cached = JSON.parse(readFileSync35(filePath, "utf-8"));
53945
54874
  return cached.phrases.length > 0 ? cached.phrases : null;
53946
54875
  } catch {
53947
54876
  return null;
53948
54877
  }
53949
54878
  }
53950
54879
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
53951
- const contextDir = join61(repoRoot, OA_DIR, "context");
53952
- mkdirSync20(contextDir, { recursive: true });
54880
+ const contextDir = join62(repoRoot, OA_DIR, "context");
54881
+ mkdirSync21(contextDir, { recursive: true });
53953
54882
  const cached = {
53954
54883
  phrases,
53955
54884
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
53956
54885
  sourceHash
53957
54886
  };
53958
- writeFileSync21(join61(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
54887
+ writeFileSync22(join62(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
53959
54888
  }
53960
54889
  function generateDescriptors(repoRoot) {
53961
54890
  const profile = loadToolProfile(repoRoot);
@@ -54003,11 +54932,11 @@ function generateDescriptors(repoRoot) {
54003
54932
  return phrases;
54004
54933
  }
54005
54934
  function extractFromPackageJson(repoRoot, tags) {
54006
- const pkgPath = join61(repoRoot, "package.json");
54935
+ const pkgPath = join62(repoRoot, "package.json");
54007
54936
  try {
54008
- if (!existsSync45(pkgPath))
54937
+ if (!existsSync46(pkgPath))
54009
54938
  return;
54010
- const pkg = JSON.parse(readFileSync34(pkgPath, "utf-8"));
54939
+ const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
54011
54940
  if (pkg.name && typeof pkg.name === "string") {
54012
54941
  const parts = pkg.name.replace(/^@/, "").split("/");
54013
54942
  for (const p of parts)
@@ -54051,7 +54980,7 @@ function extractFromManifests(repoRoot, tags) {
54051
54980
  { file: ".github/workflows", tag: "ci/cd" }
54052
54981
  ];
54053
54982
  for (const check of manifestChecks) {
54054
- if (existsSync45(join61(repoRoot, check.file))) {
54983
+ if (existsSync46(join62(repoRoot, check.file))) {
54055
54984
  tags.push(check.tag);
54056
54985
  }
54057
54986
  }
@@ -54073,16 +55002,16 @@ function extractFromSessions(repoRoot, tags) {
54073
55002
  }
54074
55003
  }
54075
55004
  function extractFromMemory(repoRoot, tags) {
54076
- const memoryDir = join61(repoRoot, OA_DIR, "memory");
55005
+ const memoryDir = join62(repoRoot, OA_DIR, "memory");
54077
55006
  try {
54078
- if (!existsSync45(memoryDir))
55007
+ if (!existsSync46(memoryDir))
54079
55008
  return;
54080
- const files = readdirSync14(memoryDir).filter((f) => f.endsWith(".json"));
55009
+ const files = readdirSync15(memoryDir).filter((f) => f.endsWith(".json"));
54081
55010
  for (const file of files) {
54082
55011
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
54083
55012
  tags.push(topic);
54084
55013
  try {
54085
- const data = JSON.parse(readFileSync34(join61(memoryDir, file), "utf-8"));
55014
+ const data = JSON.parse(readFileSync35(join62(memoryDir, file), "utf-8"));
54086
55015
  if (data && typeof data === "object") {
54087
55016
  const keys = Object.keys(data).slice(0, 3);
54088
55017
  for (const key of keys) {
@@ -54753,13 +55682,13 @@ var init_stream_renderer = __esm({
54753
55682
  });
54754
55683
 
54755
55684
  // packages/cli/dist/tui/edit-history.js
54756
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync21 } from "node:fs";
54757
- import { join as join62 } from "node:path";
55685
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync22 } from "node:fs";
55686
+ import { join as join63 } from "node:path";
54758
55687
  function createEditHistoryLogger(repoRoot, sessionId) {
54759
- const historyDir = join62(repoRoot, ".oa", "history");
54760
- const logPath2 = join62(historyDir, "edits.jsonl");
55688
+ const historyDir = join63(repoRoot, ".oa", "history");
55689
+ const logPath2 = join63(historyDir, "edits.jsonl");
54761
55690
  try {
54762
- mkdirSync21(historyDir, { recursive: true });
55691
+ mkdirSync22(historyDir, { recursive: true });
54763
55692
  } catch {
54764
55693
  }
54765
55694
  function logToolCall(toolName, toolArgs, success) {
@@ -54868,17 +55797,17 @@ var init_edit_history = __esm({
54868
55797
  });
54869
55798
 
54870
55799
  // packages/cli/dist/tui/promptLoader.js
54871
- import { readFileSync as readFileSync35, existsSync as existsSync46 } from "node:fs";
54872
- import { join as join63, dirname as dirname19 } from "node:path";
54873
- import { fileURLToPath as fileURLToPath11 } from "node:url";
55800
+ import { readFileSync as readFileSync36, existsSync as existsSync47 } from "node:fs";
55801
+ import { join as join64, dirname as dirname20 } from "node:path";
55802
+ import { fileURLToPath as fileURLToPath12 } from "node:url";
54874
55803
  function loadPrompt3(promptPath, vars) {
54875
55804
  let content = cache3.get(promptPath);
54876
55805
  if (content === void 0) {
54877
- const fullPath = join63(PROMPTS_DIR3, promptPath);
54878
- if (!existsSync46(fullPath)) {
55806
+ const fullPath = join64(PROMPTS_DIR3, promptPath);
55807
+ if (!existsSync47(fullPath)) {
54879
55808
  throw new Error(`Prompt file not found: ${fullPath}`);
54880
55809
  }
54881
- content = readFileSync35(fullPath, "utf-8");
55810
+ content = readFileSync36(fullPath, "utf-8");
54882
55811
  cache3.set(promptPath, content);
54883
55812
  }
54884
55813
  if (!vars)
@@ -54889,25 +55818,25 @@ var __filename3, __dirname6, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
54889
55818
  var init_promptLoader3 = __esm({
54890
55819
  "packages/cli/dist/tui/promptLoader.js"() {
54891
55820
  "use strict";
54892
- __filename3 = fileURLToPath11(import.meta.url);
54893
- __dirname6 = dirname19(__filename3);
54894
- devPath2 = join63(__dirname6, "..", "..", "prompts");
54895
- publishedPath2 = join63(__dirname6, "..", "prompts");
54896
- PROMPTS_DIR3 = existsSync46(devPath2) ? devPath2 : publishedPath2;
55821
+ __filename3 = fileURLToPath12(import.meta.url);
55822
+ __dirname6 = dirname20(__filename3);
55823
+ devPath2 = join64(__dirname6, "..", "..", "prompts");
55824
+ publishedPath2 = join64(__dirname6, "..", "prompts");
55825
+ PROMPTS_DIR3 = existsSync47(devPath2) ? devPath2 : publishedPath2;
54897
55826
  cache3 = /* @__PURE__ */ new Map();
54898
55827
  }
54899
55828
  });
54900
55829
 
54901
55830
  // packages/cli/dist/tui/dream-engine.js
54902
- import { mkdirSync as mkdirSync22, writeFileSync as writeFileSync22, readFileSync as readFileSync36, existsSync as existsSync47, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
54903
- import { join as join64, basename as basename14 } from "node:path";
54904
- import { execSync as execSync31 } from "node:child_process";
55831
+ import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync23, readFileSync as readFileSync37, existsSync as existsSync48, cpSync, rmSync as rmSync2, readdirSync as readdirSync16 } from "node:fs";
55832
+ import { join as join65, basename as basename14 } from "node:path";
55833
+ import { execSync as execSync32 } from "node:child_process";
54905
55834
  function loadAutoresearchMemory(repoRoot) {
54906
- const memoryPath = join64(repoRoot, ".oa", "memory", "autoresearch.json");
54907
- if (!existsSync47(memoryPath))
55835
+ const memoryPath = join65(repoRoot, ".oa", "memory", "autoresearch.json");
55836
+ if (!existsSync48(memoryPath))
54908
55837
  return "";
54909
55838
  try {
54910
- const raw = readFileSync36(memoryPath, "utf-8");
55839
+ const raw = readFileSync37(memoryPath, "utf-8");
54911
55840
  const data = JSON.parse(raw);
54912
55841
  const sections = [];
54913
55842
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -55097,14 +56026,14 @@ var init_dream_engine = __esm({
55097
56026
  const content = String(args["content"] ?? "");
55098
56027
  if (!rawPath)
55099
56028
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
55100
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join64(this.autoresearchDir, basename14(rawPath)) : join64(this.autoresearchDir, rawPath);
56029
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
55101
56030
  if (!targetPath.startsWith(this.autoresearchDir)) {
55102
56031
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
55103
56032
  }
55104
56033
  try {
55105
- const dir = join64(targetPath, "..");
55106
- mkdirSync22(dir, { recursive: true });
55107
- writeFileSync22(targetPath, content, "utf-8");
56034
+ const dir = join65(targetPath, "..");
56035
+ mkdirSync23(dir, { recursive: true });
56036
+ writeFileSync23(targetPath, content, "utf-8");
55108
56037
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
55109
56038
  } catch (err) {
55110
56039
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55132,20 +56061,20 @@ var init_dream_engine = __esm({
55132
56061
  const rawPath = String(args["path"] ?? "");
55133
56062
  const oldStr = String(args["old_string"] ?? "");
55134
56063
  const newStr = String(args["new_string"] ?? "");
55135
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join64(this.autoresearchDir, basename14(rawPath)) : join64(this.autoresearchDir, rawPath);
56064
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
55136
56065
  if (!targetPath.startsWith(this.autoresearchDir)) {
55137
56066
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
55138
56067
  }
55139
56068
  try {
55140
- if (!existsSync47(targetPath)) {
56069
+ if (!existsSync48(targetPath)) {
55141
56070
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
55142
56071
  }
55143
- let content = readFileSync36(targetPath, "utf-8");
56072
+ let content = readFileSync37(targetPath, "utf-8");
55144
56073
  if (!content.includes(oldStr)) {
55145
56074
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
55146
56075
  }
55147
56076
  content = content.replace(oldStr, newStr);
55148
- writeFileSync22(targetPath, content, "utf-8");
56077
+ writeFileSync23(targetPath, content, "utf-8");
55149
56078
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
55150
56079
  } catch (err) {
55151
56080
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55186,14 +56115,14 @@ var init_dream_engine = __esm({
55186
56115
  const content = String(args["content"] ?? "");
55187
56116
  if (!rawPath)
55188
56117
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
55189
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join64(this.dreamsDir, basename14(rawPath)) : join64(this.dreamsDir, rawPath);
56118
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
55190
56119
  if (!targetPath.startsWith(this.dreamsDir)) {
55191
56120
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
55192
56121
  }
55193
56122
  try {
55194
- const dir = join64(targetPath, "..");
55195
- mkdirSync22(dir, { recursive: true });
55196
- writeFileSync22(targetPath, content, "utf-8");
56123
+ const dir = join65(targetPath, "..");
56124
+ mkdirSync23(dir, { recursive: true });
56125
+ writeFileSync23(targetPath, content, "utf-8");
55197
56126
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
55198
56127
  } catch (err) {
55199
56128
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55221,20 +56150,20 @@ var init_dream_engine = __esm({
55221
56150
  const rawPath = String(args["path"] ?? "");
55222
56151
  const oldStr = String(args["old_string"] ?? "");
55223
56152
  const newStr = String(args["new_string"] ?? "");
55224
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join64(this.dreamsDir, basename14(rawPath)) : join64(this.dreamsDir, rawPath);
56153
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
55225
56154
  if (!targetPath.startsWith(this.dreamsDir)) {
55226
56155
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
55227
56156
  }
55228
56157
  try {
55229
- if (!existsSync47(targetPath)) {
56158
+ if (!existsSync48(targetPath)) {
55230
56159
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
55231
56160
  }
55232
- let content = readFileSync36(targetPath, "utf-8");
56161
+ let content = readFileSync37(targetPath, "utf-8");
55233
56162
  if (!content.includes(oldStr)) {
55234
56163
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
55235
56164
  }
55236
56165
  content = content.replace(oldStr, newStr);
55237
- writeFileSync22(targetPath, content, "utf-8");
56166
+ writeFileSync23(targetPath, content, "utf-8");
55238
56167
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
55239
56168
  } catch (err) {
55240
56169
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -55265,7 +56194,7 @@ var init_dream_engine = __esm({
55265
56194
  }
55266
56195
  }
55267
56196
  try {
55268
- const output = execSync31(cmd, {
56197
+ const output = execSync32(cmd, {
55269
56198
  cwd: this.repoRoot,
55270
56199
  timeout: 3e4,
55271
56200
  encoding: "utf-8",
@@ -55288,7 +56217,7 @@ var init_dream_engine = __esm({
55288
56217
  constructor(config, repoRoot) {
55289
56218
  this.config = config;
55290
56219
  this.repoRoot = repoRoot;
55291
- this.dreamsDir = join64(repoRoot, ".oa", "dreams");
56220
+ this.dreamsDir = join65(repoRoot, ".oa", "dreams");
55292
56221
  this.state = {
55293
56222
  mode: "default",
55294
56223
  active: false,
@@ -55319,7 +56248,7 @@ var init_dream_engine = __esm({
55319
56248
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
55320
56249
  results: []
55321
56250
  };
55322
- mkdirSync22(this.dreamsDir, { recursive: true });
56251
+ mkdirSync23(this.dreamsDir, { recursive: true });
55323
56252
  this.saveDreamState();
55324
56253
  try {
55325
56254
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -55372,8 +56301,8 @@ ${result.summary}`;
55372
56301
  if (mode !== "default" || cycle === totalCycles) {
55373
56302
  renderDreamContraction(cycle);
55374
56303
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
55375
- const summaryPath = join64(this.dreamsDir, `cycle-${cycle}-summary.md`);
55376
- writeFileSync22(summaryPath, cycleSummary, "utf-8");
56304
+ const summaryPath = join65(this.dreamsDir, `cycle-${cycle}-summary.md`);
56305
+ writeFileSync23(summaryPath, cycleSummary, "utf-8");
55377
56306
  }
55378
56307
  if (mode === "lucid" && !this.abortController.signal.aborted) {
55379
56308
  this.saveVersionCheckpoint(cycle);
@@ -55585,7 +56514,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
55585
56514
  }
55586
56515
  /** Build role-specific tool sets for swarm agents */
55587
56516
  buildSwarmTools(role, _workspace) {
55588
- const autoresearchDir = join64(this.repoRoot, ".oa", "autoresearch");
56517
+ const autoresearchDir = join65(this.repoRoot, ".oa", "autoresearch");
55589
56518
  const taskComplete = this.createSwarmTaskCompleteTool(role);
55590
56519
  switch (role) {
55591
56520
  case "researcher": {
@@ -55949,7 +56878,7 @@ INSTRUCTIONS:
55949
56878
  2. Summarize the key learnings and next steps
55950
56879
 
55951
56880
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
55952
- const reportPath = join64(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
56881
+ const reportPath = join65(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
55953
56882
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
55954
56883
 
55955
56884
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -55971,8 +56900,8 @@ ${summaryResult}
55971
56900
  *Generated by open-agents autoresearch swarm*
55972
56901
  `;
55973
56902
  try {
55974
- mkdirSync22(this.dreamsDir, { recursive: true });
55975
- writeFileSync22(reportPath, report, "utf-8");
56903
+ mkdirSync23(this.dreamsDir, { recursive: true });
56904
+ writeFileSync23(reportPath, report, "utf-8");
55976
56905
  } catch {
55977
56906
  }
55978
56907
  renderSwarmComplete(workspace);
@@ -56038,29 +56967,29 @@ ${summaryResult}
56038
56967
  }
56039
56968
  /** Save workspace backup for lucid mode */
56040
56969
  saveVersionCheckpoint(cycle) {
56041
- const checkpointDir = join64(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
56970
+ const checkpointDir = join65(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
56042
56971
  try {
56043
- mkdirSync22(checkpointDir, { recursive: true });
56972
+ mkdirSync23(checkpointDir, { recursive: true });
56044
56973
  try {
56045
- const gitStatus = execSync31("git status --porcelain", {
56974
+ const gitStatus = execSync32("git status --porcelain", {
56046
56975
  cwd: this.repoRoot,
56047
56976
  encoding: "utf-8",
56048
56977
  timeout: 1e4
56049
56978
  });
56050
- const gitDiff = execSync31("git diff", {
56979
+ const gitDiff = execSync32("git diff", {
56051
56980
  cwd: this.repoRoot,
56052
56981
  encoding: "utf-8",
56053
56982
  timeout: 1e4
56054
56983
  });
56055
- const gitHash = execSync31("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
56984
+ const gitHash = execSync32("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
56056
56985
  cwd: this.repoRoot,
56057
56986
  encoding: "utf-8",
56058
56987
  timeout: 5e3
56059
56988
  }).trim();
56060
- writeFileSync22(join64(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
56061
- writeFileSync22(join64(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
56062
- writeFileSync22(join64(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
56063
- writeFileSync22(join64(checkpointDir, "checkpoint.json"), JSON.stringify({
56989
+ writeFileSync23(join65(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
56990
+ writeFileSync23(join65(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
56991
+ writeFileSync23(join65(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
56992
+ writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({
56064
56993
  cycle,
56065
56994
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
56066
56995
  gitHash,
@@ -56068,7 +56997,7 @@ ${summaryResult}
56068
56997
  }, null, 2), "utf-8");
56069
56998
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
56070
56999
  } catch {
56071
- writeFileSync22(join64(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
57000
+ writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
56072
57001
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
56073
57002
  }
56074
57003
  } catch (err) {
@@ -56105,7 +57034,7 @@ Each proposal includes implementation entrypoints and estimated effort.
56105
57034
  /** Update the master proposal index */
56106
57035
  updateProposalIndex() {
56107
57036
  try {
56108
- const files = readdirSync15(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
57037
+ const files = readdirSync16(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
56109
57038
  const index = `# Dream Proposals Index
56110
57039
 
56111
57040
  **Last updated**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -56126,14 +57055,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
56126
57055
  ---
56127
57056
  *Auto-generated by open-agents dream engine*
56128
57057
  `;
56129
- writeFileSync22(join64(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
57058
+ writeFileSync23(join65(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
56130
57059
  } catch {
56131
57060
  }
56132
57061
  }
56133
57062
  /** Save dream state for resume/inspection */
56134
57063
  saveDreamState() {
56135
57064
  try {
56136
- writeFileSync22(join64(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
57065
+ writeFileSync23(join65(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
56137
57066
  } catch {
56138
57067
  }
56139
57068
  }
@@ -56507,8 +57436,8 @@ var init_bless_engine = __esm({
56507
57436
  });
56508
57437
 
56509
57438
  // packages/cli/dist/tui/dmn-engine.js
56510
- import { existsSync as existsSync48, readFileSync as readFileSync37, writeFileSync as writeFileSync23, mkdirSync as mkdirSync23, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
56511
- import { join as join65, basename as basename15 } from "node:path";
57439
+ import { existsSync as existsSync49, readFileSync as readFileSync38, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, readdirSync as readdirSync17, unlinkSync as unlinkSync10 } from "node:fs";
57440
+ import { join as join66, basename as basename15 } from "node:path";
56512
57441
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
56513
57442
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
56514
57443
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -56628,9 +57557,9 @@ var init_dmn_engine = __esm({
56628
57557
  constructor(config, repoRoot) {
56629
57558
  this.config = config;
56630
57559
  this.repoRoot = repoRoot;
56631
- this.stateDir = join65(repoRoot, ".oa", "dmn");
56632
- this.historyDir = join65(repoRoot, ".oa", "dmn", "cycles");
56633
- mkdirSync23(this.historyDir, { recursive: true });
57560
+ this.stateDir = join66(repoRoot, ".oa", "dmn");
57561
+ this.historyDir = join66(repoRoot, ".oa", "dmn", "cycles");
57562
+ mkdirSync24(this.historyDir, { recursive: true });
56634
57563
  this.loadState();
56635
57564
  }
56636
57565
  get stats() {
@@ -57219,14 +58148,14 @@ OUTPUT: Call task_complete with JSON:
57219
58148
  async gatherMemoryTopics() {
57220
58149
  const topics = [];
57221
58150
  const dirs = [
57222
- join65(this.repoRoot, ".oa", "memory"),
57223
- join65(this.repoRoot, ".open-agents", "memory")
58151
+ join66(this.repoRoot, ".oa", "memory"),
58152
+ join66(this.repoRoot, ".open-agents", "memory")
57224
58153
  ];
57225
58154
  for (const dir of dirs) {
57226
- if (!existsSync48(dir))
58155
+ if (!existsSync49(dir))
57227
58156
  continue;
57228
58157
  try {
57229
- const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
58158
+ const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
57230
58159
  for (const f of files) {
57231
58160
  const topic = basename15(f, ".json");
57232
58161
  if (!topics.includes(topic))
@@ -57239,29 +58168,29 @@ OUTPUT: Call task_complete with JSON:
57239
58168
  }
57240
58169
  // ── State persistence ─────────────────────────────────────────────────
57241
58170
  loadState() {
57242
- const path = join65(this.stateDir, "state.json");
57243
- if (existsSync48(path)) {
58171
+ const path = join66(this.stateDir, "state.json");
58172
+ if (existsSync49(path)) {
57244
58173
  try {
57245
- this.state = JSON.parse(readFileSync37(path, "utf-8"));
58174
+ this.state = JSON.parse(readFileSync38(path, "utf-8"));
57246
58175
  } catch {
57247
58176
  }
57248
58177
  }
57249
58178
  }
57250
58179
  saveState() {
57251
58180
  try {
57252
- writeFileSync23(join65(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
58181
+ writeFileSync24(join66(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
57253
58182
  } catch {
57254
58183
  }
57255
58184
  }
57256
58185
  saveCycleResult(result) {
57257
58186
  try {
57258
58187
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
57259
- writeFileSync23(join65(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
57260
- const files = readdirSync16(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
58188
+ writeFileSync24(join66(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
58189
+ const files = readdirSync17(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
57261
58190
  if (files.length > 50) {
57262
58191
  for (const old of files.slice(0, files.length - 50)) {
57263
58192
  try {
57264
- unlinkSync10(join65(this.historyDir, old));
58193
+ unlinkSync10(join66(this.historyDir, old));
57265
58194
  } catch {
57266
58195
  }
57267
58196
  }
@@ -57274,8 +58203,8 @@ OUTPUT: Call task_complete with JSON:
57274
58203
  });
57275
58204
 
57276
58205
  // packages/cli/dist/tui/snr-engine.js
57277
- import { existsSync as existsSync49, readdirSync as readdirSync17, readFileSync as readFileSync38 } from "node:fs";
57278
- import { join as join66, basename as basename16 } from "node:path";
58206
+ import { existsSync as existsSync50, readdirSync as readdirSync18, readFileSync as readFileSync39 } from "node:fs";
58207
+ import { join as join67, basename as basename16 } from "node:path";
57279
58208
  function computeDPrime(signalScores, noiseScores) {
57280
58209
  if (signalScores.length === 0 || noiseScores.length === 0)
57281
58210
  return 0;
@@ -57515,20 +58444,20 @@ Call task_complete with the JSON array when done.`, onEvent)
57515
58444
  loadMemoryEntries(topics) {
57516
58445
  const entries = [];
57517
58446
  const dirs = [
57518
- join66(this.repoRoot, ".oa", "memory"),
57519
- join66(this.repoRoot, ".open-agents", "memory")
58447
+ join67(this.repoRoot, ".oa", "memory"),
58448
+ join67(this.repoRoot, ".open-agents", "memory")
57520
58449
  ];
57521
58450
  for (const dir of dirs) {
57522
- if (!existsSync49(dir))
58451
+ if (!existsSync50(dir))
57523
58452
  continue;
57524
58453
  try {
57525
- const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
58454
+ const files = readdirSync18(dir).filter((f) => f.endsWith(".json"));
57526
58455
  for (const f of files) {
57527
58456
  const topic = basename16(f, ".json");
57528
58457
  if (topics.length > 0 && !topics.includes(topic))
57529
58458
  continue;
57530
58459
  try {
57531
- const data = JSON.parse(readFileSync38(join66(dir, f), "utf-8"));
58460
+ const data = JSON.parse(readFileSync39(join67(dir, f), "utf-8"));
57532
58461
  for (const [key, val] of Object.entries(data)) {
57533
58462
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
57534
58463
  entries.push({ topic, key, value });
@@ -58095,8 +59024,8 @@ var init_tool_policy = __esm({
58095
59024
  });
58096
59025
 
58097
59026
  // packages/cli/dist/tui/telegram-bridge.js
58098
- import { mkdirSync as mkdirSync24, existsSync as existsSync50, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
58099
- import { join as join67, resolve as resolve30 } from "node:path";
59027
+ import { mkdirSync as mkdirSync25, existsSync as existsSync51, unlinkSync as unlinkSync11, readdirSync as readdirSync19, statSync as statSync15 } from "node:fs";
59028
+ import { join as join68, resolve as resolve30 } from "node:path";
58100
59029
  import { writeFile as writeFileAsync } from "node:fs/promises";
58101
59030
  function convertMarkdownToTelegramHTML(md) {
58102
59031
  let html = md;
@@ -58424,7 +59353,7 @@ with summary "no_reply" to silently skip without responding.
58424
59353
  this.polling = true;
58425
59354
  this.abortController = new AbortController();
58426
59355
  try {
58427
- mkdirSync24(this.mediaCacheDir, { recursive: true });
59356
+ mkdirSync25(this.mediaCacheDir, { recursive: true });
58428
59357
  } catch {
58429
59358
  }
58430
59359
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -58861,7 +59790,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
58861
59790
  return null;
58862
59791
  const buffer = Buffer.from(await res.arrayBuffer());
58863
59792
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
58864
- const localPath = join67(this.mediaCacheDir, fileName);
59793
+ const localPath = join68(this.mediaCacheDir, fileName);
58865
59794
  await writeFileAsync(localPath, buffer);
58866
59795
  return localPath;
58867
59796
  } catch {
@@ -59877,7 +60806,7 @@ __export(text_selection_exports, {
59877
60806
  stripAnsi: () => stripAnsi3,
59878
60807
  visibleLength: () => visibleLength
59879
60808
  });
59880
- import { execSync as execSync32 } from "node:child_process";
60809
+ import { execSync as execSync33 } from "node:child_process";
59881
60810
  function stripAnsi3(s) {
59882
60811
  return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
59883
60812
  }
@@ -59888,16 +60817,16 @@ function copyText(text) {
59888
60817
  try {
59889
60818
  const platform6 = process.platform;
59890
60819
  if (platform6 === "darwin") {
59891
- execSync32("pbcopy", { input: text, timeout: 3e3 });
60820
+ execSync33("pbcopy", { input: text, timeout: 3e3 });
59892
60821
  return true;
59893
60822
  }
59894
60823
  if (platform6 === "win32") {
59895
- execSync32("clip", { input: text, timeout: 3e3 });
60824
+ execSync33("clip", { input: text, timeout: 3e3 });
59896
60825
  return true;
59897
60826
  }
59898
60827
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
59899
60828
  try {
59900
- execSync32(tool, { input: text, timeout: 3e3 });
60829
+ execSync33(tool, { input: text, timeout: 3e3 });
59901
60830
  return true;
59902
60831
  } catch {
59903
60832
  continue;
@@ -59906,10 +60835,10 @@ function copyText(text) {
59906
60835
  if (!_clipboardAutoInstallAttempted) {
59907
60836
  _clipboardAutoInstallAttempted = true;
59908
60837
  try {
59909
- execSync32("which apt-get", { timeout: 2e3, stdio: "pipe" });
60838
+ execSync33("which apt-get", { timeout: 2e3, stdio: "pipe" });
59910
60839
  try {
59911
- execSync32("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
59912
- execSync32("xclip -selection clipboard", { input: text, timeout: 3e3 });
60840
+ execSync33("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
60841
+ execSync33("xclip -selection clipboard", { input: text, timeout: 3e3 });
59913
60842
  return true;
59914
60843
  } catch {
59915
60844
  }
@@ -60217,7 +61146,7 @@ var init_text_selection = __esm({
60217
61146
  });
60218
61147
 
60219
61148
  // packages/cli/dist/tui/status-bar.js
60220
- import { readFileSync as readFileSync39 } from "node:fs";
61149
+ import { readFileSync as readFileSync40 } from "node:fs";
60221
61150
  function setTerminalTitle(task, version) {
60222
61151
  if (!process.stdout.isTTY)
60223
61152
  return;
@@ -60914,7 +61843,7 @@ var init_status_bar = __esm({
60914
61843
  if (nexusDir) {
60915
61844
  try {
60916
61845
  const metricsPath = nexusDir + "/remote-metrics.json";
60917
- const raw = readFileSync39(metricsPath, "utf8");
61846
+ const raw = readFileSync40(metricsPath, "utf8");
60918
61847
  const cached = JSON.parse(raw);
60919
61848
  if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
60920
61849
  const m = cached.data;
@@ -63207,24 +64136,24 @@ var init_direct_input = __esm({
63207
64136
  });
63208
64137
 
63209
64138
  // packages/cli/dist/api/profiles.js
63210
- import { existsSync as existsSync51, readFileSync as readFileSync40, writeFileSync as writeFileSync24, mkdirSync as mkdirSync25, readdirSync as readdirSync19, unlinkSync as unlinkSync12 } from "node:fs";
63211
- import { join as join68 } from "node:path";
63212
- import { homedir as homedir17 } from "node:os";
64139
+ import { existsSync as existsSync52, readFileSync as readFileSync41, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26, readdirSync as readdirSync20, unlinkSync as unlinkSync12 } from "node:fs";
64140
+ import { join as join69 } from "node:path";
64141
+ import { homedir as homedir18 } from "node:os";
63213
64142
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
63214
64143
  function globalProfileDir() {
63215
- return join68(homedir17(), ".open-agents", "profiles");
64144
+ return join69(homedir18(), ".open-agents", "profiles");
63216
64145
  }
63217
64146
  function projectProfileDir(projectDir) {
63218
- return join68(projectDir || process.cwd(), ".oa", "profiles");
64147
+ return join69(projectDir || process.cwd(), ".oa", "profiles");
63219
64148
  }
63220
64149
  function listProfiles(projectDir) {
63221
64150
  const result = [];
63222
64151
  const seen = /* @__PURE__ */ new Set();
63223
64152
  const projDir = projectProfileDir(projectDir);
63224
- if (existsSync51(projDir)) {
63225
- for (const f of readdirSync19(projDir).filter((f2) => f2.endsWith(".json"))) {
64153
+ if (existsSync52(projDir)) {
64154
+ for (const f of readdirSync20(projDir).filter((f2) => f2.endsWith(".json"))) {
63226
64155
  try {
63227
- const raw = JSON.parse(readFileSync40(join68(projDir, f), "utf8"));
64156
+ const raw = JSON.parse(readFileSync41(join69(projDir, f), "utf8"));
63228
64157
  const name = f.replace(".json", "");
63229
64158
  seen.add(name);
63230
64159
  result.push({
@@ -63238,13 +64167,13 @@ function listProfiles(projectDir) {
63238
64167
  }
63239
64168
  }
63240
64169
  const globDir = globalProfileDir();
63241
- if (existsSync51(globDir)) {
63242
- for (const f of readdirSync19(globDir).filter((f2) => f2.endsWith(".json"))) {
64170
+ if (existsSync52(globDir)) {
64171
+ for (const f of readdirSync20(globDir).filter((f2) => f2.endsWith(".json"))) {
63243
64172
  const name = f.replace(".json", "");
63244
64173
  if (seen.has(name))
63245
64174
  continue;
63246
64175
  try {
63247
- const raw = JSON.parse(readFileSync40(join68(globDir, f), "utf8"));
64176
+ const raw = JSON.parse(readFileSync41(join69(globDir, f), "utf8"));
63248
64177
  result.push({
63249
64178
  name,
63250
64179
  description: raw.description || "",
@@ -63259,12 +64188,12 @@ function listProfiles(projectDir) {
63259
64188
  }
63260
64189
  function loadProfile(name, password, projectDir) {
63261
64190
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
63262
- const projPath = join68(projectProfileDir(projectDir), `${sanitized}.json`);
63263
- const globPath = join68(globalProfileDir(), `${sanitized}.json`);
63264
- const filePath = existsSync51(projPath) ? projPath : existsSync51(globPath) ? globPath : null;
64191
+ const projPath = join69(projectProfileDir(projectDir), `${sanitized}.json`);
64192
+ const globPath = join69(globalProfileDir(), `${sanitized}.json`);
64193
+ const filePath = existsSync52(projPath) ? projPath : existsSync52(globPath) ? globPath : null;
63265
64194
  if (!filePath)
63266
64195
  return null;
63267
- const raw = JSON.parse(readFileSync40(filePath, "utf8"));
64196
+ const raw = JSON.parse(readFileSync41(filePath, "utf8"));
63268
64197
  if (raw.encrypted === true) {
63269
64198
  if (!password)
63270
64199
  return null;
@@ -63274,23 +64203,23 @@ function loadProfile(name, password, projectDir) {
63274
64203
  }
63275
64204
  function saveProfile(profile, password, scope = "global", projectDir) {
63276
64205
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
63277
- mkdirSync25(dir, { recursive: true });
64206
+ mkdirSync26(dir, { recursive: true });
63278
64207
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
63279
- const filePath = join68(dir, `${sanitized}.json`);
64208
+ const filePath = join69(dir, `${sanitized}.json`);
63280
64209
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
63281
64210
  if (password) {
63282
64211
  const encrypted = encryptProfile(profile, password);
63283
- writeFileSync24(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
64212
+ writeFileSync25(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
63284
64213
  } else {
63285
64214
  profile.encrypted = false;
63286
- writeFileSync24(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
64215
+ writeFileSync25(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
63287
64216
  }
63288
64217
  }
63289
64218
  function deleteProfile(name, scope = "global", projectDir) {
63290
64219
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
63291
64220
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
63292
- const filePath = join68(dir, `${sanitized}.json`);
63293
- if (existsSync51(filePath)) {
64221
+ const filePath = join69(dir, `${sanitized}.json`);
64222
+ if (existsSync52(filePath)) {
63294
64223
  unlinkSync12(filePath);
63295
64224
  return true;
63296
64225
  }
@@ -63382,23 +64311,23 @@ __export(serve_exports, {
63382
64311
  import * as http from "node:http";
63383
64312
  import * as https from "node:https";
63384
64313
  import { createRequire as createRequire3 } from "node:module";
63385
- import { fileURLToPath as fileURLToPath12 } from "node:url";
63386
- import { dirname as dirname20, join as join69, resolve as resolve31 } from "node:path";
63387
- import { spawn as spawn20 } from "node:child_process";
63388
- import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync25, readFileSync as readFileSync41, readdirSync as readdirSync20, existsSync as existsSync52 } from "node:fs";
64314
+ import { fileURLToPath as fileURLToPath13 } from "node:url";
64315
+ import { dirname as dirname21, join as join70, resolve as resolve31 } from "node:path";
64316
+ import { spawn as spawn21 } from "node:child_process";
64317
+ import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26, readFileSync as readFileSync42, readdirSync as readdirSync21, existsSync as existsSync53 } from "node:fs";
63389
64318
  import { randomBytes as randomBytes16 } from "node:crypto";
63390
64319
  function getVersion3() {
63391
64320
  try {
63392
64321
  const require2 = createRequire3(import.meta.url);
63393
- const thisDir = dirname20(fileURLToPath12(import.meta.url));
64322
+ const thisDir = dirname21(fileURLToPath13(import.meta.url));
63394
64323
  const candidates = [
63395
- join69(thisDir, "..", "package.json"),
63396
- join69(thisDir, "..", "..", "package.json"),
63397
- join69(thisDir, "..", "..", "..", "package.json")
64324
+ join70(thisDir, "..", "package.json"),
64325
+ join70(thisDir, "..", "..", "package.json"),
64326
+ join70(thisDir, "..", "..", "..", "package.json")
63398
64327
  ];
63399
64328
  for (const pkgPath of candidates) {
63400
64329
  try {
63401
- if (!existsSync52(pkgPath))
64330
+ if (!existsSync53(pkgPath))
63402
64331
  continue;
63403
64332
  const pkg = require2(pkgPath);
63404
64333
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
@@ -63693,29 +64622,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
63693
64622
  }
63694
64623
  function jobsDir() {
63695
64624
  const root = resolve31(process.cwd());
63696
- const dir = join69(root, ".oa", "jobs");
63697
- mkdirSync26(dir, { recursive: true });
64625
+ const dir = join70(root, ".oa", "jobs");
64626
+ mkdirSync27(dir, { recursive: true });
63698
64627
  return dir;
63699
64628
  }
63700
64629
  function loadJob(id) {
63701
- const file = join69(jobsDir(), `${id}.json`);
63702
- if (!existsSync52(file))
64630
+ const file = join70(jobsDir(), `${id}.json`);
64631
+ if (!existsSync53(file))
63703
64632
  return null;
63704
64633
  try {
63705
- return JSON.parse(readFileSync41(file, "utf-8"));
64634
+ return JSON.parse(readFileSync42(file, "utf-8"));
63706
64635
  } catch {
63707
64636
  return null;
63708
64637
  }
63709
64638
  }
63710
64639
  function listJobs() {
63711
64640
  const dir = jobsDir();
63712
- if (!existsSync52(dir))
64641
+ if (!existsSync53(dir))
63713
64642
  return [];
63714
- const files = readdirSync20(dir).filter((f) => f.endsWith(".json")).sort();
64643
+ const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).sort();
63715
64644
  const jobs = [];
63716
64645
  for (const file of files) {
63717
64646
  try {
63718
- jobs.push(JSON.parse(readFileSync41(join69(dir, file), "utf-8")));
64647
+ jobs.push(JSON.parse(readFileSync42(join70(dir, file), "utf-8")));
63719
64648
  } catch {
63720
64649
  }
63721
64650
  }
@@ -64108,8 +65037,8 @@ async function handleV1Run(req, res) {
64108
65037
  if (workingDir) {
64109
65038
  cwd4 = resolve31(workingDir);
64110
65039
  } else if (isolate) {
64111
- const wsDir = join69(dir, "..", "workspaces", id);
64112
- mkdirSync26(wsDir, { recursive: true });
65040
+ const wsDir = join70(dir, "..", "workspaces", id);
65041
+ mkdirSync27(wsDir, { recursive: true });
64113
65042
  cwd4 = wsDir;
64114
65043
  } else {
64115
65044
  cwd4 = resolve31(process.cwd());
@@ -64173,7 +65102,7 @@ async function handleV1Run(req, res) {
64173
65102
  }
64174
65103
  }
64175
65104
  }
64176
- const child = spawn20("node", [oaBin, ...args], {
65105
+ const child = spawn21("node", [oaBin, ...args], {
64177
65106
  cwd: cwd4,
64178
65107
  env: runEnv,
64179
65108
  stdio: ["ignore", "pipe", "pipe"],
@@ -64181,7 +65110,7 @@ async function handleV1Run(req, res) {
64181
65110
  });
64182
65111
  child.unref();
64183
65112
  job.pid = child.pid ?? 0;
64184
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
65113
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64185
65114
  runningProcesses.set(id, child);
64186
65115
  if (streamMode) {
64187
65116
  res.writeHead(200, {
@@ -64211,7 +65140,7 @@ async function handleV1Run(req, res) {
64211
65140
  job.status = code === 0 ? "completed" : "failed";
64212
65141
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
64213
65142
  try {
64214
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
65143
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64215
65144
  } catch {
64216
65145
  }
64217
65146
  runningProcesses.delete(id);
@@ -64242,7 +65171,7 @@ async function handleV1Run(req, res) {
64242
65171
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
64243
65172
  }
64244
65173
  try {
64245
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
65174
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64246
65175
  } catch {
64247
65176
  }
64248
65177
  runningProcesses.delete(id);
@@ -64283,7 +65212,7 @@ function handleV1RunsDelete(res, id) {
64283
65212
  job.error = "Aborted via API";
64284
65213
  const dir = jobsDir();
64285
65214
  try {
64286
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
65215
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
64287
65216
  } catch {
64288
65217
  }
64289
65218
  runningProcesses.delete(id);
@@ -64395,7 +65324,7 @@ async function handlePostCommand(res, cmd) {
64395
65324
  return;
64396
65325
  }
64397
65326
  try {
64398
- const child = spawn20("node", [oaBin, "run", `/${cmd}`, "--json"], {
65327
+ const child = spawn21("node", [oaBin, "run", `/${cmd}`, "--json"], {
64399
65328
  env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
64400
65329
  stdio: ["ignore", "pipe", "pipe"],
64401
65330
  timeout: 3e4
@@ -64808,13 +65737,13 @@ var init_serve = __esm({
64808
65737
 
64809
65738
  // packages/cli/dist/tui/interactive.js
64810
65739
  import { cwd } from "node:process";
64811
- import { resolve as resolve32, join as join70, dirname as dirname21, extname as extname11 } from "node:path";
65740
+ import { resolve as resolve32, join as join71, dirname as dirname22, extname as extname11 } from "node:path";
64812
65741
  import { createRequire as createRequire4 } from "node:module";
64813
- import { fileURLToPath as fileURLToPath13 } from "node:url";
64814
- import { readFileSync as readFileSync42, writeFileSync as writeFileSync26, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync21, mkdirSync as mkdirSync27 } from "node:fs";
64815
- import { existsSync as existsSync53 } from "node:fs";
64816
- import { execSync as execSync33 } from "node:child_process";
64817
- import { homedir as homedir18 } from "node:os";
65742
+ import { fileURLToPath as fileURLToPath14 } from "node:url";
65743
+ import { readFileSync as readFileSync43, writeFileSync as writeFileSync27, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync22, mkdirSync as mkdirSync28 } from "node:fs";
65744
+ import { existsSync as existsSync54 } from "node:fs";
65745
+ import { execSync as execSync34 } from "node:child_process";
65746
+ import { homedir as homedir19 } from "node:os";
64818
65747
  function formatTimeAgo(date) {
64819
65748
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
64820
65749
  if (seconds < 60)
@@ -64831,14 +65760,14 @@ function formatTimeAgo(date) {
64831
65760
  function getVersion4() {
64832
65761
  try {
64833
65762
  const require2 = createRequire4(import.meta.url);
64834
- const thisDir = dirname21(fileURLToPath13(import.meta.url));
65763
+ const thisDir = dirname22(fileURLToPath14(import.meta.url));
64835
65764
  const candidates = [
64836
- join70(thisDir, "..", "package.json"),
64837
- join70(thisDir, "..", "..", "package.json"),
64838
- join70(thisDir, "..", "..", "..", "package.json")
65765
+ join71(thisDir, "..", "package.json"),
65766
+ join71(thisDir, "..", "..", "package.json"),
65767
+ join71(thisDir, "..", "..", "..", "package.json")
64839
65768
  ];
64840
65769
  for (const pkgPath of candidates) {
64841
- if (existsSync53(pkgPath)) {
65770
+ if (existsSync54(pkgPath)) {
64842
65771
  const pkg = require2(pkgPath);
64843
65772
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
64844
65773
  return pkg.version ?? "0.0.0";
@@ -65074,15 +66003,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
65074
66003
  function gatherMemorySnippets(root) {
65075
66004
  const snippets = [];
65076
66005
  const dirs = [
65077
- join70(root, ".oa", "memory"),
65078
- join70(root, ".open-agents", "memory")
66006
+ join71(root, ".oa", "memory"),
66007
+ join71(root, ".open-agents", "memory")
65079
66008
  ];
65080
66009
  for (const dir of dirs) {
65081
- if (!existsSync53(dir))
66010
+ if (!existsSync54(dir))
65082
66011
  continue;
65083
66012
  try {
65084
- for (const f of readdirSync21(dir).filter((f2) => f2.endsWith(".json"))) {
65085
- const data = JSON.parse(readFileSync42(join70(dir, f), "utf-8"));
66013
+ for (const f of readdirSync22(dir).filter((f2) => f2.endsWith(".json"))) {
66014
+ const data = JSON.parse(readFileSync43(join71(dir, f), "utf-8"));
65086
66015
  for (const val of Object.values(data)) {
65087
66016
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
65088
66017
  if (v.length > 10)
@@ -65239,9 +66168,9 @@ ${metabolismMemories}
65239
66168
  } catch {
65240
66169
  }
65241
66170
  try {
65242
- const archeFile = join70(repoRoot, ".oa", "arche", "variants.json");
65243
- if (existsSync53(archeFile)) {
65244
- const variants = JSON.parse(readFileSync42(archeFile, "utf8"));
66171
+ const archeFile = join71(repoRoot, ".oa", "arche", "variants.json");
66172
+ if (existsSync54(archeFile)) {
66173
+ const variants = JSON.parse(readFileSync43(archeFile, "utf8"));
65245
66174
  if (variants.length > 0) {
65246
66175
  let filtered = variants;
65247
66176
  if (taskType) {
@@ -65410,9 +66339,9 @@ RULES:
65410
66339
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
65411
66340
  let identityInjection = "";
65412
66341
  try {
65413
- const ikStateFile = join70(repoRoot, ".oa", "identity", "self-state.json");
65414
- if (existsSync53(ikStateFile)) {
65415
- const selfState = JSON.parse(readFileSync42(ikStateFile, "utf8"));
66342
+ const ikStateFile = join71(repoRoot, ".oa", "identity", "self-state.json");
66343
+ if (existsSync54(ikStateFile)) {
66344
+ const selfState = JSON.parse(readFileSync43(ikStateFile, "utf8"));
65416
66345
  const lines = [
65417
66346
  `[Identity State v${selfState.version}]`,
65418
66347
  `Self: ${selfState.narrative_summary}`,
@@ -66055,13 +66984,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66055
66984
  });
66056
66985
  }
66057
66986
  try {
66058
- const ikDir = join70(repoRoot, ".oa", "identity");
66059
- const ikFile = join70(ikDir, "self-state.json");
66987
+ const ikDir = join71(repoRoot, ".oa", "identity");
66988
+ const ikFile = join71(ikDir, "self-state.json");
66060
66989
  let ikState;
66061
- if (existsSync53(ikFile)) {
66062
- ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
66990
+ if (existsSync54(ikFile)) {
66991
+ ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
66063
66992
  } else {
66064
- mkdirSync27(ikDir, { recursive: true });
66993
+ mkdirSync28(ikDir, { recursive: true });
66065
66994
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
66066
66995
  ikState = {
66067
66996
  self_id: `oa-${machineId}`,
@@ -66087,7 +67016,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66087
67016
  }
66088
67017
  ikState.session_count = (ikState.session_count || 0) + 1;
66089
67018
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
66090
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
67019
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
66091
67020
  } catch (ikErr) {
66092
67021
  try {
66093
67022
  console.error("[IK-OBSERVE]", ikErr);
@@ -66102,14 +67031,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
66102
67031
  } else {
66103
67032
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
66104
67033
  try {
66105
- const ikFile = join70(repoRoot, ".oa", "identity", "self-state.json");
66106
- if (existsSync53(ikFile)) {
66107
- const ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
67034
+ const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
67035
+ if (existsSync54(ikFile)) {
67036
+ const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
66108
67037
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
66109
67038
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
66110
67039
  ikState.session_count = (ikState.session_count || 0) + 1;
66111
67040
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
66112
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
67041
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
66113
67042
  }
66114
67043
  } catch {
66115
67044
  }
@@ -66206,10 +67135,10 @@ async function startInteractive(config, repoPath) {
66206
67135
  process.stdin.pause();
66207
67136
  }
66208
67137
  try {
66209
- const oaDir = join70(repoRoot, ".oa");
66210
- const nexusPidFile = join70(oaDir, "nexus", "daemon.pid");
66211
- if (existsSync53(nexusPidFile)) {
66212
- const pid = parseInt(readFileSync42(nexusPidFile, "utf8").trim(), 10);
67138
+ const oaDir = join71(repoRoot, ".oa");
67139
+ const nexusPidFile = join71(oaDir, "nexus", "daemon.pid");
67140
+ if (existsSync54(nexusPidFile)) {
67141
+ const pid = parseInt(readFileSync43(nexusPidFile, "utf8").trim(), 10);
66213
67142
  if (pid > 0) {
66214
67143
  try {
66215
67144
  process.kill(pid, 0);
@@ -66518,7 +67447,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
66518
67447
  let p2pGateway = null;
66519
67448
  let peerMesh = null;
66520
67449
  let inferenceRouter = null;
66521
- const secretVault = new SecretVault(join70(repoRoot, ".oa", "vault.enc"));
67450
+ const secretVault = new SecretVault(join71(repoRoot, ".oa", "vault.enc"));
66522
67451
  let adminSessionKey = null;
66523
67452
  const callSubAgents = /* @__PURE__ */ new Map();
66524
67453
  const streamRenderer = new StreamRenderer();
@@ -66741,13 +67670,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
66741
67670
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
66742
67671
  return [hits, line];
66743
67672
  }
66744
- const HISTORY_DIR = join70(homedir18(), ".open-agents");
66745
- const HISTORY_FILE = join70(HISTORY_DIR, "repl-history");
67673
+ const HISTORY_DIR = join71(homedir19(), ".open-agents");
67674
+ const HISTORY_FILE = join71(HISTORY_DIR, "repl-history");
66746
67675
  const MAX_HISTORY_LINES = 500;
66747
67676
  let savedHistory = [];
66748
67677
  try {
66749
- if (existsSync53(HISTORY_FILE)) {
66750
- const raw = readFileSync42(HISTORY_FILE, "utf8").trim();
67678
+ if (existsSync54(HISTORY_FILE)) {
67679
+ const raw = readFileSync43(HISTORY_FILE, "utf8").trim();
66751
67680
  if (raw)
66752
67681
  savedHistory = raw.split("\n").reverse();
66753
67682
  }
@@ -66850,12 +67779,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
66850
67779
  if (!line.trim())
66851
67780
  return;
66852
67781
  try {
66853
- mkdirSync27(HISTORY_DIR, { recursive: true });
67782
+ mkdirSync28(HISTORY_DIR, { recursive: true });
66854
67783
  appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
66855
67784
  if (Math.random() < 0.02) {
66856
- const all = readFileSync42(HISTORY_FILE, "utf8").trim().split("\n");
67785
+ const all = readFileSync43(HISTORY_FILE, "utf8").trim().split("\n");
66857
67786
  if (all.length > MAX_HISTORY_LINES) {
66858
- writeFileSync26(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
67787
+ writeFileSync27(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
66859
67788
  }
66860
67789
  }
66861
67790
  } catch {
@@ -67039,7 +67968,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67039
67968
  } catch {
67040
67969
  }
67041
67970
  try {
67042
- const oaDir = join70(repoRoot, ".oa");
67971
+ const oaDir = join71(repoRoot, ".oa");
67043
67972
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
67044
67973
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
67045
67974
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -67071,7 +68000,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67071
68000
  } catch {
67072
68001
  }
67073
68002
  try {
67074
- const oaDir = join70(repoRoot, ".oa");
68003
+ const oaDir = join71(repoRoot, ".oa");
67075
68004
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
67076
68005
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
67077
68006
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -67112,11 +68041,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
67112
68041
  }
67113
68042
  try {
67114
68043
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
67115
- const globalNamePath = join70(_hd(), ".open-agents", "agent-name");
68044
+ const globalNamePath = join71(_hd(), ".open-agents", "agent-name");
67116
68045
  let agName = "";
67117
68046
  try {
67118
- if (existsSync53(globalNamePath))
67119
- agName = readFileSync42(globalNamePath, "utf8").trim();
68047
+ if (existsSync54(globalNamePath))
68048
+ agName = readFileSync43(globalNamePath, "utf8").trim();
67120
68049
  } catch {
67121
68050
  }
67122
68051
  if (!agName) {
@@ -67894,6 +68823,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
67894
68823
  adminSessionKey = generateSessionKey();
67895
68824
  }
67896
68825
  voiceSession = new VoiceSession();
68826
+ try {
68827
+ const { isPersonaPlexRunning: isPersonaPlexRunning2, getPersonaPlexWSUrl: getPersonaPlexWSUrl2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
68828
+ if (isPersonaPlexRunning2()) {
68829
+ const ppUrl = getPersonaPlexWSUrl2();
68830
+ if (ppUrl) {
68831
+ voiceSession.personaPlexWsUrl = ppUrl;
68832
+ writeContent(() => renderInfo(`PersonaPlex active \u2014 full-duplex mode at ${ppUrl}`));
68833
+ }
68834
+ }
68835
+ } catch {
68836
+ }
67897
68837
  const callState = {
67898
68838
  transcribers: /* @__PURE__ */ new Map(),
67899
68839
  loading: false,
@@ -68081,7 +69021,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68081
69021
  kind,
68082
69022
  targetUrl,
68083
69023
  authKey,
68084
- stateDir: join70(repoRoot, ".oa"),
69024
+ stateDir: join71(repoRoot, ".oa"),
68085
69025
  passthrough: passthrough ?? false,
68086
69026
  loadbalance: loadbalance ?? false,
68087
69027
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -68129,7 +69069,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68129
69069
  await tunnelGateway.stop();
68130
69070
  tunnelGateway = null;
68131
69071
  }
68132
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join70(repoRoot, ".oa") });
69072
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join71(repoRoot, ".oa") });
68133
69073
  newTunnel.on("stats", (stats) => {
68134
69074
  statusBar.setExposeStatus({
68135
69075
  status: stats.status,
@@ -68401,15 +69341,15 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68401
69341
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
68402
69342
  }
68403
69343
  try {
68404
- const nexusDir = join70(repoRoot, OA_DIR, "nexus");
68405
- const pidFile = join70(nexusDir, "daemon.pid");
68406
- if (existsSync53(pidFile)) {
68407
- const pid = parseInt(readFileSync42(pidFile, "utf8").trim(), 10);
69344
+ const nexusDir = join71(repoRoot, OA_DIR, "nexus");
69345
+ const pidFile = join71(nexusDir, "daemon.pid");
69346
+ if (existsSync54(pidFile)) {
69347
+ const pid = parseInt(readFileSync43(pidFile, "utf8").trim(), 10);
68408
69348
  if (pid > 0) {
68409
69349
  try {
68410
69350
  if (process.platform === "win32") {
68411
69351
  try {
68412
- execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
69352
+ execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68413
69353
  } catch {
68414
69354
  }
68415
69355
  } else {
@@ -68426,17 +69366,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68426
69366
  } catch {
68427
69367
  }
68428
69368
  try {
68429
- const voiceDir2 = join70(homedir18(), ".open-agents", "voice");
69369
+ const voiceDir2 = join71(homedir19(), ".open-agents", "voice");
68430
69370
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
68431
69371
  for (const pf of voicePidFiles) {
68432
- const pidPath = join70(voiceDir2, pf);
68433
- if (existsSync53(pidPath)) {
69372
+ const pidPath = join71(voiceDir2, pf);
69373
+ if (existsSync54(pidPath)) {
68434
69374
  try {
68435
- const pid = parseInt(readFileSync42(pidPath, "utf8").trim(), 10);
69375
+ const pid = parseInt(readFileSync43(pidPath, "utf8").trim(), 10);
68436
69376
  if (pid > 0) {
68437
69377
  if (process.platform === "win32") {
68438
69378
  try {
68439
- execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
69379
+ execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
68440
69380
  } catch {
68441
69381
  }
68442
69382
  } else {
@@ -68453,11 +69393,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68453
69393
  } catch {
68454
69394
  }
68455
69395
  try {
68456
- execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
69396
+ execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
68457
69397
  } catch {
68458
69398
  }
68459
- const oaPath = join70(repoRoot, OA_DIR);
68460
- if (existsSync53(oaPath)) {
69399
+ const oaPath = join71(repoRoot, OA_DIR);
69400
+ if (existsSync54(oaPath)) {
68461
69401
  let deleted = false;
68462
69402
  for (let attempt = 0; attempt < 3; attempt++) {
68463
69403
  try {
@@ -68467,14 +69407,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
68467
69407
  } catch (err) {
68468
69408
  if (attempt < 2) {
68469
69409
  try {
68470
- execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
69410
+ execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
68471
69411
  } catch {
68472
69412
  }
68473
69413
  } else {
68474
69414
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
68475
69415
  if (process.platform === "win32") {
68476
69416
  try {
68477
- execSync33(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
69417
+ execSync34(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
68478
69418
  deleted = true;
68479
69419
  } catch {
68480
69420
  }
@@ -68867,8 +69807,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
68867
69807
  }
68868
69808
  }
68869
69809
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
68870
- const isImage = isImagePath(cleanPath) && existsSync53(resolve32(repoRoot, cleanPath));
68871
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync53(resolve32(repoRoot, cleanPath));
69810
+ const isImage = isImagePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
69811
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
68872
69812
  if (activeTask) {
68873
69813
  if (activeTask.runner.isPaused) {
68874
69814
  activeTask.runner.resume();
@@ -68877,7 +69817,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
68877
69817
  if (isImage) {
68878
69818
  try {
68879
69819
  const imgPath = resolve32(repoRoot, cleanPath);
68880
- const imgBuffer = readFileSync42(imgPath);
69820
+ const imgBuffer = readFileSync43(imgPath);
68881
69821
  const base64 = imgBuffer.toString("base64");
68882
69822
  const ext = extname11(cleanPath).toLowerCase();
68883
69823
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -69405,13 +70345,13 @@ async function runWithTUI(task, config, repoPath) {
69405
70345
  const handle = startTask(task, config, repoRoot);
69406
70346
  await handle.promise;
69407
70347
  try {
69408
- const ikDir = join70(repoRoot, ".oa", "identity");
69409
- const ikFile = join70(ikDir, "self-state.json");
70348
+ const ikDir = join71(repoRoot, ".oa", "identity");
70349
+ const ikFile = join71(ikDir, "self-state.json");
69410
70350
  let ikState;
69411
- if (existsSync53(ikFile)) {
69412
- ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
70351
+ if (existsSync54(ikFile)) {
70352
+ ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
69413
70353
  } else {
69414
- mkdirSync27(ikDir, { recursive: true });
70354
+ mkdirSync28(ikDir, { recursive: true });
69415
70355
  ikState = {
69416
70356
  self_id: `oa-${Date.now().toString(36)}`,
69417
70357
  version: 1,
@@ -69433,7 +70373,7 @@ async function runWithTUI(task, config, repoPath) {
69433
70373
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
69434
70374
  ikState.session_count = (ikState.session_count || 0) + 1;
69435
70375
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69436
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
70376
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69437
70377
  } catch (ikErr) {
69438
70378
  }
69439
70379
  try {
@@ -69442,12 +70382,12 @@ async function runWithTUI(task, config, repoPath) {
69442
70382
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
69443
70383
  } catch {
69444
70384
  try {
69445
- const archeDir = join70(repoRoot, ".oa", "arche");
69446
- const archeFile = join70(archeDir, "variants.json");
70385
+ const archeDir = join71(repoRoot, ".oa", "arche");
70386
+ const archeFile = join71(archeDir, "variants.json");
69447
70387
  let variants = [];
69448
70388
  try {
69449
- if (existsSync53(archeFile))
69450
- variants = JSON.parse(readFileSync42(archeFile, "utf8"));
70389
+ if (existsSync54(archeFile))
70390
+ variants = JSON.parse(readFileSync43(archeFile, "utf8"));
69451
70391
  } catch {
69452
70392
  }
69453
70393
  variants.push({
@@ -69462,15 +70402,15 @@ async function runWithTUI(task, config, repoPath) {
69462
70402
  });
69463
70403
  if (variants.length > 50)
69464
70404
  variants = variants.slice(-50);
69465
- mkdirSync27(archeDir, { recursive: true });
69466
- writeFileSync26(archeFile, JSON.stringify(variants, null, 2));
70405
+ mkdirSync28(archeDir, { recursive: true });
70406
+ writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
69467
70407
  } catch {
69468
70408
  }
69469
70409
  }
69470
70410
  try {
69471
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69472
- if (existsSync53(metaFile)) {
69473
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
70411
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
70412
+ if (existsSync54(metaFile)) {
70413
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69474
70414
  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);
69475
70415
  let updated = false;
69476
70416
  for (const item of surfaced) {
@@ -69481,7 +70421,7 @@ async function runWithTUI(task, config, repoPath) {
69481
70421
  updated = true;
69482
70422
  }
69483
70423
  if (updated) {
69484
- writeFileSync26(metaFile, JSON.stringify(store, null, 2));
70424
+ writeFileSync27(metaFile, JSON.stringify(store, null, 2));
69485
70425
  }
69486
70426
  }
69487
70427
  } catch {
@@ -69534,9 +70474,9 @@ Rules:
69534
70474
  try {
69535
70475
  const { initDb: initDb2 } = __require("@open-agents/memory");
69536
70476
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
69537
- const dbDir = join70(repoRoot, ".oa", "memory");
69538
- mkdirSync27(dbDir, { recursive: true });
69539
- const db = initDb2(join70(dbDir, "structured.db"));
70477
+ const dbDir = join71(repoRoot, ".oa", "memory");
70478
+ mkdirSync28(dbDir, { recursive: true });
70479
+ const db = initDb2(join71(dbDir, "structured.db"));
69540
70480
  const memStore = new ProceduralMemoryStore2(db);
69541
70481
  memStore.createWithEmbedding({
69542
70482
  content: content.slice(0, 600),
@@ -69551,12 +70491,12 @@ Rules:
69551
70491
  db.close();
69552
70492
  } catch {
69553
70493
  }
69554
- const metaDir = join70(repoRoot, ".oa", "memory", "metabolism");
69555
- const storeFile = join70(metaDir, "store.json");
70494
+ const metaDir = join71(repoRoot, ".oa", "memory", "metabolism");
70495
+ const storeFile = join71(metaDir, "store.json");
69556
70496
  let store = [];
69557
70497
  try {
69558
- if (existsSync53(storeFile))
69559
- store = JSON.parse(readFileSync42(storeFile, "utf8"));
70498
+ if (existsSync54(storeFile))
70499
+ store = JSON.parse(readFileSync43(storeFile, "utf8"));
69560
70500
  } catch {
69561
70501
  }
69562
70502
  store.push({
@@ -69572,26 +70512,26 @@ Rules:
69572
70512
  });
69573
70513
  if (store.length > 100)
69574
70514
  store = store.slice(-100);
69575
- mkdirSync27(metaDir, { recursive: true });
69576
- writeFileSync26(storeFile, JSON.stringify(store, null, 2));
70515
+ mkdirSync28(metaDir, { recursive: true });
70516
+ writeFileSync27(storeFile, JSON.stringify(store, null, 2));
69577
70517
  }
69578
70518
  }
69579
70519
  } catch {
69580
70520
  }
69581
70521
  try {
69582
- const cohereSettingsFile = join70(repoRoot, ".oa", "settings.json");
70522
+ const cohereSettingsFile = join71(repoRoot, ".oa", "settings.json");
69583
70523
  let cohereActive = false;
69584
70524
  try {
69585
- if (existsSync53(cohereSettingsFile)) {
69586
- const settings = JSON.parse(readFileSync42(cohereSettingsFile, "utf8"));
70525
+ if (existsSync54(cohereSettingsFile)) {
70526
+ const settings = JSON.parse(readFileSync43(cohereSettingsFile, "utf8"));
69587
70527
  cohereActive = settings.cohere === true;
69588
70528
  }
69589
70529
  } catch {
69590
70530
  }
69591
70531
  if (cohereActive) {
69592
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69593
- if (existsSync53(metaFile)) {
69594
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
70532
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
70533
+ if (existsSync54(metaFile)) {
70534
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69595
70535
  const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
69596
70536
  if (latest && latest.scores?.confidence >= 0.6) {
69597
70537
  try {
@@ -69616,18 +70556,18 @@ Rules:
69616
70556
  }
69617
70557
  } catch (err) {
69618
70558
  try {
69619
- const ikFile = join70(repoRoot, ".oa", "identity", "self-state.json");
69620
- if (existsSync53(ikFile)) {
69621
- const ikState = JSON.parse(readFileSync42(ikFile, "utf8"));
70559
+ const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
70560
+ if (existsSync54(ikFile)) {
70561
+ const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
69622
70562
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
69623
70563
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
69624
70564
  ikState.session_count = (ikState.session_count || 0) + 1;
69625
70565
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69626
- writeFileSync26(ikFile, JSON.stringify(ikState, null, 2));
70566
+ writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69627
70567
  }
69628
- const metaFile = join70(repoRoot, ".oa", "memory", "metabolism", "store.json");
69629
- if (existsSync53(metaFile)) {
69630
- const store = JSON.parse(readFileSync42(metaFile, "utf8"));
70568
+ const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
70569
+ if (existsSync54(metaFile)) {
70570
+ const store = JSON.parse(readFileSync43(metaFile, "utf8"));
69631
70571
  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);
69632
70572
  for (const item of surfaced) {
69633
70573
  item.accessCount = (item.accessCount || 0) + 1;
@@ -69635,15 +70575,15 @@ Rules:
69635
70575
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
69636
70576
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
69637
70577
  }
69638
- writeFileSync26(metaFile, JSON.stringify(store, null, 2));
70578
+ writeFileSync27(metaFile, JSON.stringify(store, null, 2));
69639
70579
  }
69640
70580
  try {
69641
- const archeDir = join70(repoRoot, ".oa", "arche");
69642
- const archeFile = join70(archeDir, "variants.json");
70581
+ const archeDir = join71(repoRoot, ".oa", "arche");
70582
+ const archeFile = join71(archeDir, "variants.json");
69643
70583
  let variants = [];
69644
70584
  try {
69645
- if (existsSync53(archeFile))
69646
- variants = JSON.parse(readFileSync42(archeFile, "utf8"));
70585
+ if (existsSync54(archeFile))
70586
+ variants = JSON.parse(readFileSync43(archeFile, "utf8"));
69647
70587
  } catch {
69648
70588
  }
69649
70589
  variants.push({
@@ -69658,8 +70598,8 @@ Rules:
69658
70598
  });
69659
70599
  if (variants.length > 50)
69660
70600
  variants = variants.slice(-50);
69661
- mkdirSync27(archeDir, { recursive: true });
69662
- writeFileSync26(archeFile, JSON.stringify(variants, null, 2));
70601
+ mkdirSync28(archeDir, { recursive: true });
70602
+ writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
69663
70603
  } catch {
69664
70604
  }
69665
70605
  } catch {
@@ -69725,14 +70665,14 @@ __export(run_exports, {
69725
70665
  statusCommand: () => statusCommand
69726
70666
  });
69727
70667
  import { resolve as resolve33 } from "node:path";
69728
- import { spawn as spawn21 } from "node:child_process";
69729
- import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync27, readFileSync as readFileSync43, readdirSync as readdirSync22, existsSync as existsSync54 } from "node:fs";
70668
+ import { spawn as spawn22 } from "node:child_process";
70669
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync28, readFileSync as readFileSync44, readdirSync as readdirSync23, existsSync as existsSync55 } from "node:fs";
69730
70670
  import { randomBytes as randomBytes17 } from "node:crypto";
69731
- import { join as join71 } from "node:path";
70671
+ import { join as join72 } from "node:path";
69732
70672
  function jobsDir2(repoPath) {
69733
70673
  const root = resolve33(repoPath ?? process.cwd());
69734
- const dir = join71(root, ".oa", "jobs");
69735
- mkdirSync28(dir, { recursive: true });
70674
+ const dir = join72(root, ".oa", "jobs");
70675
+ mkdirSync29(dir, { recursive: true });
69736
70676
  return dir;
69737
70677
  }
69738
70678
  async function runCommand(opts, config) {
@@ -69809,7 +70749,7 @@ async function runBackground(task, config, opts) {
69809
70749
  const args = [task, "--json"];
69810
70750
  if (config.model)
69811
70751
  args.push("--model", config.model);
69812
- const child = spawn21("node", [oaBin, ...args], {
70752
+ const child = spawn22("node", [oaBin, ...args], {
69813
70753
  cwd: repoRoot,
69814
70754
  env: { ...process.env, OA_JOB_ID: id },
69815
70755
  stdio: ["ignore", "pipe", "pipe"],
@@ -69817,7 +70757,7 @@ async function runBackground(task, config, opts) {
69817
70757
  });
69818
70758
  child.unref();
69819
70759
  job.pid = child.pid ?? 0;
69820
- writeFileSync27(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
70760
+ writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
69821
70761
  let output = "";
69822
70762
  child.stdout?.on("data", (chunk) => {
69823
70763
  output += chunk.toString();
@@ -69833,7 +70773,7 @@ async function runBackground(task, config, opts) {
69833
70773
  job.summary = result.summary;
69834
70774
  job.durationMs = result.durationMs;
69835
70775
  job.error = result.error;
69836
- writeFileSync27(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
70776
+ writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
69837
70777
  } catch {
69838
70778
  }
69839
70779
  });
@@ -69849,13 +70789,13 @@ async function runBackground(task, config, opts) {
69849
70789
  }
69850
70790
  function statusCommand(jobId, repoPath) {
69851
70791
  const dir = jobsDir2(repoPath);
69852
- const file = join71(dir, `${jobId}.json`);
69853
- if (!existsSync54(file)) {
70792
+ const file = join72(dir, `${jobId}.json`);
70793
+ if (!existsSync55(file)) {
69854
70794
  console.error(`Job not found: ${jobId}`);
69855
70795
  console.log(`Available jobs: oa jobs`);
69856
70796
  process.exit(1);
69857
70797
  }
69858
- const job = JSON.parse(readFileSync43(file, "utf-8"));
70798
+ const job = JSON.parse(readFileSync44(file, "utf-8"));
69859
70799
  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`;
69860
70800
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
69861
70801
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -69870,7 +70810,7 @@ function statusCommand(jobId, repoPath) {
69870
70810
  }
69871
70811
  function jobsCommand(repoPath) {
69872
70812
  const dir = jobsDir2(repoPath);
69873
- const files = readdirSync22(dir).filter((f) => f.endsWith(".json")).sort();
70813
+ const files = readdirSync23(dir).filter((f) => f.endsWith(".json")).sort();
69874
70814
  if (files.length === 0) {
69875
70815
  console.log("No jobs found.");
69876
70816
  return;
@@ -69878,7 +70818,7 @@ function jobsCommand(repoPath) {
69878
70818
  console.log("Jobs:");
69879
70819
  for (const file of files) {
69880
70820
  try {
69881
- const job = JSON.parse(readFileSync43(join71(dir, file), "utf-8"));
70821
+ const job = JSON.parse(readFileSync44(join72(dir, file), "utf-8"));
69882
70822
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
69883
70823
  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`;
69884
70824
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -69898,7 +70838,7 @@ import { glob } from "glob";
69898
70838
  import ignore from "ignore";
69899
70839
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
69900
70840
  import { createHash as createHash6 } from "node:crypto";
69901
- import { join as join72, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
70841
+ import { join as join73, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
69902
70842
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
69903
70843
  var init_codebase_indexer = __esm({
69904
70844
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -69942,7 +70882,7 @@ var init_codebase_indexer = __esm({
69942
70882
  const ig = ignore.default();
69943
70883
  if (this.config.respectGitignore) {
69944
70884
  try {
69945
- const gitignoreContent = await readFile23(join72(this.config.rootDir, ".gitignore"), "utf-8");
70885
+ const gitignoreContent = await readFile23(join73(this.config.rootDir, ".gitignore"), "utf-8");
69946
70886
  ig.add(gitignoreContent);
69947
70887
  } catch {
69948
70888
  }
@@ -69957,7 +70897,7 @@ var init_codebase_indexer = __esm({
69957
70897
  for (const relativePath of files) {
69958
70898
  if (ig.ignores(relativePath))
69959
70899
  continue;
69960
- const fullPath = join72(this.config.rootDir, relativePath);
70900
+ const fullPath = join73(this.config.rootDir, relativePath);
69961
70901
  try {
69962
70902
  const fileStat = await stat4(fullPath);
69963
70903
  if (fileStat.size > this.config.maxFileSize)
@@ -70003,7 +70943,7 @@ var init_codebase_indexer = __esm({
70003
70943
  if (!child) {
70004
70944
  child = {
70005
70945
  name: part,
70006
- path: join72(current.path, part),
70946
+ path: join73(current.path, part),
70007
70947
  type: "directory",
70008
70948
  children: []
70009
70949
  };
@@ -70086,13 +71026,13 @@ __export(index_repo_exports, {
70086
71026
  indexRepoCommand: () => indexRepoCommand
70087
71027
  });
70088
71028
  import { resolve as resolve34 } from "node:path";
70089
- import { existsSync as existsSync55, statSync as statSync16 } from "node:fs";
71029
+ import { existsSync as existsSync56, statSync as statSync16 } from "node:fs";
70090
71030
  import { cwd as cwd2 } from "node:process";
70091
71031
  async function indexRepoCommand(opts, _config) {
70092
71032
  const repoRoot = resolve34(opts.repoPath ?? cwd2());
70093
71033
  printHeader("Index Repository");
70094
71034
  printInfo(`Indexing: ${repoRoot}`);
70095
- if (!existsSync55(repoRoot)) {
71035
+ if (!existsSync56(repoRoot)) {
70096
71036
  printError(`Path does not exist: ${repoRoot}`);
70097
71037
  process.exit(1);
70098
71038
  }
@@ -70344,8 +71284,8 @@ var config_exports2 = {};
70344
71284
  __export(config_exports2, {
70345
71285
  configCommand: () => configCommand
70346
71286
  });
70347
- import { join as join73, resolve as resolve35 } from "node:path";
70348
- import { homedir as homedir19 } from "node:os";
71287
+ import { join as join74, resolve as resolve35 } from "node:path";
71288
+ import { homedir as homedir20 } from "node:os";
70349
71289
  import { cwd as cwd3 } from "node:process";
70350
71290
  function redactIfSensitive(key, value) {
70351
71291
  if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
@@ -70427,7 +71367,7 @@ function handleShow(opts, config) {
70427
71367
  }
70428
71368
  }
70429
71369
  printSection("Config File");
70430
- printInfo(`~/.open-agents/config.json (${join73(homedir19(), ".open-agents", "config.json")})`);
71370
+ printInfo(`~/.open-agents/config.json (${join74(homedir20(), ".open-agents", "config.json")})`);
70431
71371
  printSection("Priority Chain");
70432
71372
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
70433
71373
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -70466,7 +71406,7 @@ function handleSet(opts, _config) {
70466
71406
  const coerced = coerceForSettings(key, value);
70467
71407
  saveProjectSettings(repoRoot, { [key]: coerced });
70468
71408
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
70469
- printInfo(`Saved to ${join73(repoRoot, ".oa", "settings.json")}`);
71409
+ printInfo(`Saved to ${join74(repoRoot, ".oa", "settings.json")}`);
70470
71410
  printInfo("This override applies only when running in this workspace.");
70471
71411
  } catch (err) {
70472
71412
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -70609,8 +71549,8 @@ __export(eval_exports, {
70609
71549
  evalCommand: () => evalCommand
70610
71550
  });
70611
71551
  import { tmpdir as tmpdir10 } from "node:os";
70612
- import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync28 } from "node:fs";
70613
- import { join as join74 } from "node:path";
71552
+ import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync29 } from "node:fs";
71553
+ import { join as join75 } from "node:path";
70614
71554
  async function evalCommand(opts, config) {
70615
71555
  const suiteName = opts.suite ?? "basic";
70616
71556
  const suite = SUITES[suiteName];
@@ -70735,9 +71675,9 @@ async function evalCommand(opts, config) {
70735
71675
  process.exit(failed > 0 ? 1 : 0);
70736
71676
  }
70737
71677
  function createTempEvalRepo() {
70738
- const dir = join74(tmpdir10(), `open-agents-eval-${Date.now()}`);
70739
- mkdirSync29(dir, { recursive: true });
70740
- writeFileSync28(join74(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
71678
+ const dir = join75(tmpdir10(), `open-agents-eval-${Date.now()}`);
71679
+ mkdirSync30(dir, { recursive: true });
71680
+ writeFileSync29(join75(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
70741
71681
  return dir;
70742
71682
  }
70743
71683
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -70796,8 +71736,8 @@ init_output();
70796
71736
  init_updater();
70797
71737
  import { parseArgs as nodeParseArgs2 } from "node:util";
70798
71738
  import { createRequire as createRequire5 } from "node:module";
70799
- import { fileURLToPath as fileURLToPath14 } from "node:url";
70800
- import { dirname as dirname22, join as join75 } from "node:path";
71739
+ import { fileURLToPath as fileURLToPath15 } from "node:url";
71740
+ import { dirname as dirname23, join as join76 } from "node:path";
70801
71741
 
70802
71742
  // packages/cli/dist/cli.js
70803
71743
  import { createInterface } from "node:readline";
@@ -70904,7 +71844,7 @@ init_output();
70904
71844
  function getVersion5() {
70905
71845
  try {
70906
71846
  const require2 = createRequire5(import.meta.url);
70907
- const pkgPath = join75(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
71847
+ const pkgPath = join76(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
70908
71848
  const pkg = require2(pkgPath);
70909
71849
  return pkg.version;
70910
71850
  } catch {
@@ -71179,12 +72119,12 @@ function crashLog(label, err) {
71179
72119
  const logLine = `[${timestamp}] ${label}: ${msg}
71180
72120
  `;
71181
72121
  try {
71182
- const { appendFileSync: appendFileSync5, mkdirSync: mkdirSync30 } = __require("node:fs");
71183
- const { join: join76 } = __require("node:path");
71184
- const { homedir: homedir20 } = __require("node:os");
71185
- const logDir = join76(homedir20(), ".open-agents");
71186
- mkdirSync30(logDir, { recursive: true });
71187
- appendFileSync5(join76(logDir, "crash.log"), logLine);
72122
+ const { appendFileSync: appendFileSync5, mkdirSync: mkdirSync31 } = __require("node:fs");
72123
+ const { join: join77 } = __require("node:path");
72124
+ const { homedir: homedir21 } = __require("node:os");
72125
+ const logDir = join77(homedir21(), ".open-agents");
72126
+ mkdirSync31(logDir, { recursive: true });
72127
+ appendFileSync5(join77(logDir, "crash.log"), logLine);
71188
72128
  } catch {
71189
72129
  }
71190
72130
  try {