open-agents-ai 0.187.15 → 0.187.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12136,8 +12136,8 @@ function deleteCustomToolDefinition(name10, scope, repoRoot) {
12136
12136
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
12137
12137
  const filePath = join16(dir, `${name10}.json`);
12138
12138
  if (existsSync13(filePath)) {
12139
- const { unlinkSync: unlinkSync13 } = __require("node:fs");
12140
- unlinkSync13(filePath);
12139
+ const { unlinkSync: unlinkSync14 } = __require("node:fs");
12140
+ unlinkSync14(filePath);
12141
12141
  return true;
12142
12142
  }
12143
12143
  return false;
@@ -13111,6 +13111,10 @@ var init_skill_builder = __esm({
13111
13111
  validate: {
13112
13112
  type: "boolean",
13113
13113
  description: "Whether to run the validation phase (default: true). Validation scores the generated skill and suggests improvements."
13114
+ },
13115
+ session_corrections: {
13116
+ type: "string",
13117
+ description: "Optional: corrections and failed approaches from the current session. Each correction becomes a hard rule in the generated SKILL.md. Format: one correction per line, e.g. 'FAILED: file_write too large \u2014 use file_edit instead'"
13114
13118
  }
13115
13119
  },
13116
13120
  required: ["skill_request"]
@@ -13134,9 +13138,10 @@ var init_skill_builder = __esm({
13134
13138
  durationMs: performance.now() - start2
13135
13139
  };
13136
13140
  }
13141
+ const sessionCorrections = String(args["session_corrections"] ?? "").trim();
13137
13142
  try {
13138
13143
  const seed = await this.analyzeSeed(skillRequest);
13139
- let skillContent = await this.expandSkill(seed);
13144
+ let skillContent = await this.expandSkill(seed, sessionCorrections);
13140
13145
  let validationInfo = "";
13141
13146
  if (shouldValidate) {
13142
13147
  const validation = await this.validateSkill(skillContent);
@@ -13205,15 +13210,21 @@ Validation: ${validation.pass ? "PASS" : "NEEDS IMPROVEMENT"} (${validation.over
13205
13210
  // -------------------------------------------------------------------------
13206
13211
  // Phase 2: Skill Expansion
13207
13212
  // -------------------------------------------------------------------------
13208
- async expandSkill(seed) {
13213
+ async expandSkill(seed, sessionCorrections) {
13209
13214
  const prompt = loadBuilderPrompt("skill-expansion.md", {
13210
13215
  seed_json: JSON.stringify(seed, null, 2)
13211
13216
  });
13217
+ const correctionBlock = sessionCorrections ? `
13218
+
13219
+ IMPORTANT \u2014 Session Corrections (encode as hard rules in the Rules section):
13220
+ These represent things that FAILED or were CORRECTED during the reference session.
13221
+ Each MUST appear as a rule in the generated SKILL.md:
13222
+ ${sessionCorrections}` : "";
13212
13223
  const response = await this.llmCall([
13213
13224
  { role: "system", content: prompt },
13214
13225
  {
13215
13226
  role: "user",
13216
- content: `Generate the complete SKILL.md for the "${seed.name}" skill.`
13227
+ content: `Generate the complete SKILL.md for the "${seed.name}" skill.${correctionBlock}`
13217
13228
  }
13218
13229
  ]);
13219
13230
  let content = response.trim();
@@ -123831,7 +123842,7 @@ var require_snapshot_recorder = __commonJS({
123831
123842
  "../node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
123832
123843
  "use strict";
123833
123844
  var { writeFile: writeFile21, readFile: readFile24, mkdir: mkdir16 } = __require("node:fs/promises");
123834
- var { dirname: dirname26, resolve: resolve39 } = __require("node:path");
123845
+ var { dirname: dirname27, resolve: resolve39 } = __require("node:path");
123835
123846
  var { setTimeout: setTimeout3, clearTimeout: clearTimeout3 } = __require("node:timers");
123836
123847
  var { InvalidArgumentError, UndiciError } = require_errors2();
123837
123848
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -124062,7 +124073,7 @@ var require_snapshot_recorder = __commonJS({
124062
124073
  throw new InvalidArgumentError("Snapshot path is required");
124063
124074
  }
124064
124075
  const resolvedPath = resolve39(path5);
124065
- await mkdir16(dirname26(resolvedPath), { recursive: true });
124076
+ await mkdir16(dirname27(resolvedPath), { recursive: true });
124066
124077
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
124067
124078
  hash,
124068
124079
  snapshot
@@ -237724,15 +237735,15 @@ var init_ls = __esm({
237724
237735
  });
237725
237736
 
237726
237737
  // ../node_modules/@helia/unixfs/dist/src/commands/mkdir.js
237727
- async function mkdir5(parentCid, dirname26, blockstore, options2 = {}) {
237728
- if (dirname26.includes("/")) {
237738
+ async function mkdir5(parentCid, dirname27, blockstore, options2 = {}) {
237739
+ if (dirname27.includes("/")) {
237729
237740
  throw new InvalidParametersError4("Path must not have slashes");
237730
237741
  }
237731
237742
  const entry = await exporter2(parentCid, blockstore, options2);
237732
237743
  if (entry.type !== "directory") {
237733
237744
  throw new NotADirectoryError(`${parentCid.toString()} was not a UnixFS directory`);
237734
237745
  }
237735
- log16("creating %s", dirname26);
237746
+ log16("creating %s", dirname27);
237736
237747
  const metadata = new UnixFS({
237737
237748
  type: "directory",
237738
237749
  mode: options2.mode,
@@ -237748,9 +237759,9 @@ async function mkdir5(parentCid, dirname26, blockstore, options2 = {}) {
237748
237759
  await blockstore.put(emptyDirCid, buf);
237749
237760
  const [directory, pblink] = await Promise.all([
237750
237761
  cidToDirectory(parentCid, blockstore, options2),
237751
- cidToPBLink(emptyDirCid, dirname26, blockstore, options2)
237762
+ cidToPBLink(emptyDirCid, dirname27, blockstore, options2)
237752
237763
  ]);
237753
- log16("adding empty dir called %s to %c", dirname26, parentCid);
237764
+ log16("adding empty dir called %s to %c", dirname27, parentCid);
237754
237765
  const result = await addLink(directory, pblink, blockstore, {
237755
237766
  ...options2,
237756
237767
  allowOverwriting: options2.force
@@ -238249,8 +238260,8 @@ var init_unixfs2 = __esm({
238249
238260
  async *ls(cid, options2 = {}) {
238250
238261
  yield* ls(cid, this.components.blockstore, options2);
238251
238262
  }
238252
- async mkdir(cid, dirname26, options2 = {}) {
238253
- return mkdir5(cid, dirname26, this.components.blockstore, options2);
238263
+ async mkdir(cid, dirname27, options2 = {}) {
238264
+ return mkdir5(cid, dirname27, this.components.blockstore, options2);
238254
238265
  }
238255
238266
  async rm(cid, path5, options2 = {}) {
238256
238267
  return rm2(cid, path5, this.components.blockstore, options2);
@@ -245494,9 +245505,9 @@ print("${sentinel}")
245494
245505
  if (!this.proc || this.proc.killed) {
245495
245506
  return { success: false, path: "" };
245496
245507
  }
245497
- const { mkdirSync: mkdirSync36, writeFileSync: writeFileSync34 } = await import("node:fs");
245508
+ const { mkdirSync: mkdirSync37, writeFileSync: writeFileSync35 } = await import("node:fs");
245498
245509
  const sessionDir = join23(this.cwd, ".oa", "rlm");
245499
- mkdirSync36(sessionDir, { recursive: true });
245510
+ mkdirSync37(sessionDir, { recursive: true });
245500
245511
  const sessionPath = join23(sessionDir, "session.json");
245501
245512
  try {
245502
245513
  const inspectCode = `
@@ -245520,7 +245531,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
245520
245531
  trajectoryCount: this.trajectory.length,
245521
245532
  subCallCount: this.subCallCount
245522
245533
  };
245523
- writeFileSync34(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
245534
+ writeFileSync35(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
245524
245535
  return { success: true, path: sessionPath };
245525
245536
  }
245526
245537
  } catch {
@@ -245532,11 +245543,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
245532
245543
  * what was previously computed. */
245533
245544
  async loadSessionInfo() {
245534
245545
  try {
245535
- const { readFileSync: readFileSync52, existsSync: existsSync66 } = await import("node:fs");
245546
+ const { readFileSync: readFileSync53, existsSync: existsSync67 } = await import("node:fs");
245536
245547
  const sessionPath = join23(this.cwd, ".oa", "rlm", "session.json");
245537
- if (!existsSync66(sessionPath))
245548
+ if (!existsSync67(sessionPath))
245538
245549
  return null;
245539
- return JSON.parse(readFileSync52(sessionPath, "utf8"));
245550
+ return JSON.parse(readFileSync53(sessionPath, "utf8"));
245540
245551
  } catch {
245541
245552
  return null;
245542
245553
  }
@@ -245713,10 +245724,10 @@ var init_memory_metabolism = __esm({
245713
245724
  const trajDir = join24(this.cwd, ".oa", "rlm-trajectories");
245714
245725
  let lessons = [];
245715
245726
  try {
245716
- const { readdirSync: readdirSync26, readFileSync: readFileSync52 } = await import("node:fs");
245727
+ const { readdirSync: readdirSync26, readFileSync: readFileSync53 } = await import("node:fs");
245717
245728
  const files = readdirSync26(trajDir).filter((f2) => f2.endsWith(".jsonl")).sort().reverse().slice(0, 3);
245718
245729
  for (const file of files) {
245719
- const lines = readFileSync52(join24(trajDir, file), "utf8").split("\n").filter((l2) => l2.trim());
245730
+ const lines = readFileSync53(join24(trajDir, file), "utf8").split("\n").filter((l2) => l2.trim());
245720
245731
  for (const line of lines) {
245721
245732
  try {
245722
245733
  const entry = JSON.parse(line);
@@ -246100,14 +246111,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
246100
246111
  * Optionally filter by task type for phase-aware context (FSM paper insight).
246101
246112
  */
246102
246113
  getTopMemoriesSync(k = 5, taskType) {
246103
- const { readFileSync: readFileSync52, existsSync: existsSync66 } = __require("node:fs");
246114
+ const { readFileSync: readFileSync53, existsSync: existsSync67 } = __require("node:fs");
246104
246115
  const metaDir = join24(this.cwd, ".oa", "memory", "metabolism");
246105
246116
  const storeFile = join24(metaDir, "store.json");
246106
- if (!existsSync66(storeFile))
246117
+ if (!existsSync67(storeFile))
246107
246118
  return "";
246108
246119
  let store2 = [];
246109
246120
  try {
246110
- store2 = JSON.parse(readFileSync52(storeFile, "utf8"));
246121
+ store2 = JSON.parse(readFileSync53(storeFile, "utf8"));
246111
246122
  } catch {
246112
246123
  return "";
246113
246124
  }
@@ -246129,14 +246140,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
246129
246140
  /** Update memory scores based on task outcome. Called after task completion.
246130
246141
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
246131
246142
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
246132
- const { readFileSync: readFileSync52, writeFileSync: writeFileSync34, existsSync: existsSync66, mkdirSync: mkdirSync36 } = __require("node:fs");
246143
+ const { readFileSync: readFileSync53, writeFileSync: writeFileSync35, existsSync: existsSync67, mkdirSync: mkdirSync37 } = __require("node:fs");
246133
246144
  const metaDir = join24(this.cwd, ".oa", "memory", "metabolism");
246134
246145
  const storeFile = join24(metaDir, "store.json");
246135
- if (!existsSync66(storeFile))
246146
+ if (!existsSync67(storeFile))
246136
246147
  return;
246137
246148
  let store2 = [];
246138
246149
  try {
246139
- store2 = JSON.parse(readFileSync52(storeFile, "utf8"));
246150
+ store2 = JSON.parse(readFileSync53(storeFile, "utf8"));
246140
246151
  } catch {
246141
246152
  return;
246142
246153
  }
@@ -246160,8 +246171,8 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
246160
246171
  updated = true;
246161
246172
  }
246162
246173
  if (updated) {
246163
- mkdirSync36(metaDir, { recursive: true });
246164
- writeFileSync34(storeFile, JSON.stringify(store2, null, 2));
246174
+ mkdirSync37(metaDir, { recursive: true });
246175
+ writeFileSync35(storeFile, JSON.stringify(store2, null, 2));
246165
246176
  }
246166
246177
  }
246167
246178
  // ── Storage ──────────────────────────────────────────────────────────
@@ -246583,13 +246594,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
246583
246594
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
246584
246595
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
246585
246596
  getRelevantStrategiesSync(k = 3, taskType) {
246586
- const { readFileSync: readFileSync52, existsSync: existsSync66 } = __require("node:fs");
246597
+ const { readFileSync: readFileSync53, existsSync: existsSync67 } = __require("node:fs");
246587
246598
  const archiveFile = join26(this.cwd, ".oa", "arche", "variants.json");
246588
- if (!existsSync66(archiveFile))
246599
+ if (!existsSync67(archiveFile))
246589
246600
  return "";
246590
246601
  let variants = [];
246591
246602
  try {
246592
- variants = JSON.parse(readFileSync52(archiveFile, "utf8"));
246603
+ variants = JSON.parse(readFileSync53(archiveFile, "utf8"));
246593
246604
  } catch {
246594
246605
  return "";
246595
246606
  }
@@ -246607,13 +246618,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
246607
246618
  }
246608
246619
  /** Archive a strategy variant synchronously (for task completion path) */
246609
246620
  archiveVariantSync(strategy, outcome, tags = []) {
246610
- const { readFileSync: readFileSync52, writeFileSync: writeFileSync34, existsSync: existsSync66, mkdirSync: mkdirSync36 } = __require("node:fs");
246621
+ const { readFileSync: readFileSync53, writeFileSync: writeFileSync35, existsSync: existsSync67, mkdirSync: mkdirSync37 } = __require("node:fs");
246611
246622
  const dir = join26(this.cwd, ".oa", "arche");
246612
246623
  const archiveFile = join26(dir, "variants.json");
246613
246624
  let variants = [];
246614
246625
  try {
246615
- if (existsSync66(archiveFile))
246616
- variants = JSON.parse(readFileSync52(archiveFile, "utf8"));
246626
+ if (existsSync67(archiveFile))
246627
+ variants = JSON.parse(readFileSync53(archiveFile, "utf8"));
246617
246628
  } catch {
246618
246629
  }
246619
246630
  variants.push({
@@ -246628,8 +246639,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
246628
246639
  });
246629
246640
  if (variants.length > 50)
246630
246641
  variants = variants.slice(-50);
246631
- mkdirSync36(dir, { recursive: true });
246632
- writeFileSync34(archiveFile, JSON.stringify(variants, null, 2));
246642
+ mkdirSync37(dir, { recursive: true });
246643
+ writeFileSync35(archiveFile, JSON.stringify(variants, null, 2));
246633
246644
  }
246634
246645
  async saveArchive(variants) {
246635
246646
  const dir = join26(this.cwd, ".oa", "arche");
@@ -249445,8 +249456,8 @@ var init_browser_action = __esm({
249445
249456
  const afterDom = await apiCall("/dom", "GET");
249446
249457
  const afterTitle = (afterDom.dom || "").match(/<title[^>]*>([^<]*)<\/title>/i)?.[1] || "";
249447
249458
  try {
249448
- const { unlinkSync: unlinkSync13 } = await import("node:fs");
249449
- unlinkSync13(imagePath);
249459
+ const { unlinkSync: unlinkSync14 } = await import("node:fs");
249460
+ unlinkSync14(imagePath);
249450
249461
  } catch {
249451
249462
  }
249452
249463
  return {
@@ -253603,7 +253614,7 @@ var init_agent_tool = __esm({
253603
253614
  const label = description ?? `${subagentType}: ${prompt.slice(0, 40)}`;
253604
253615
  if (isolation === "worktree") {
253605
253616
  this.callbacks.onViewRegister?.(agentId, label);
253606
- const spawn25 = this.callbacks.spawnSubprocess({
253617
+ const spawn26 = this.callbacks.spawnSubprocess({
253607
253618
  id: agentId,
253608
253619
  task: prompt,
253609
253620
  model,
@@ -253613,7 +253624,7 @@ var init_agent_tool = __esm({
253613
253624
  success: true,
253614
253625
  output: `Agent spawned (subprocess, worktree): ${agentId}
253615
253626
  Type: ${subagentType}
253616
- PID: ${spawn25.pid}
253627
+ PID: ${spawn26.pid}
253617
253628
  Task: ${prompt.slice(0, 100)}
253618
253629
  Use task_status("${agentId}") to check progress.`,
253619
253630
  durationMs: performance.now() - start2
@@ -260098,6 +260109,10 @@ var init_agenticRunner = __esm({
260098
260109
  // WO-E26: prevent double-emit
260099
260110
  _recentEnoents = [];
260100
260111
  // sliding window of last 8 tool calls
260112
+ _microcompactHintEmitted = false;
260113
+ // WO-LL-02: one memory hint per session
260114
+ _hookDenyHintCount = 0;
260115
+ // WO-LL-02: cap hint injection at 3 per session
260101
260116
  // -- Session Checkpointing (Priority 5) --
260102
260117
  _sessionId = `session-${Date.now()}`;
260103
260118
  _workingDirectory = "";
@@ -260326,6 +260341,10 @@ ${ctx3}`,
260326
260341
  content: `Microcompact: cleared ${cleared} old tool result(s), keeping ${keepResults} recent`,
260327
260342
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
260328
260343
  });
260344
+ if (!this._microcompactHintEmitted) {
260345
+ this._microcompactHintEmitted = true;
260346
+ this.pendingUserMessages.push(`[SYSTEM] Older tool results have been cleared to save context. If you discovered important patterns or facts, use memory_write to persist them before they are lost from context.`);
260347
+ }
260329
260348
  }
260330
260349
  }
260331
260350
  /** Register a tool for the agent to use */
@@ -260577,6 +260596,8 @@ TASK: ${task}` : task;
260577
260596
  let summary = "";
260578
260597
  let bruteForceCycle = 0;
260579
260598
  this._assistantTextEmitted = false;
260599
+ this._microcompactHintEmitted = false;
260600
+ this._hookDenyHintCount = 0;
260580
260601
  let pendingConstraintWarnings = [];
260581
260602
  let consecutiveTextOnly = 0;
260582
260603
  let loopInterventionCount = 0;
@@ -261094,6 +261115,10 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
261094
261115
  reason: hookCheck.reason ?? "hook",
261095
261116
  source: "hook"
261096
261117
  });
261118
+ if (this._hookDenyHintCount < 3) {
261119
+ this._hookDenyHintCount++;
261120
+ this.pendingUserMessages.push(`[SYSTEM] Tool "${tc.name}" was blocked: ${hookCheck.reason}. If this constraint should persist across sessions, use memory_write to save it (e.g., memory_write(topic="constraints", key="${tc.name}_blocked", value="${(hookCheck.reason ?? "hook").slice(0, 80)}")).`);
261121
+ }
261097
261122
  } else {
261098
261123
  const finalArgs = hookCheck.modifiedArgs ?? tc.arguments;
261099
261124
  try {
@@ -261189,6 +261214,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
261189
261214
  if (this._taskState.failedApproaches.length > 10) {
261190
261215
  this._taskState.failedApproaches.shift();
261191
261216
  }
261217
+ if (this._taskState.failedApproaches.length === 3) {
261218
+ this.pendingUserMessages.push(`[SYSTEM] You have ${this._taskState.failedApproaches.length} failed approaches this session. Consider using memory_write to save these failure patterns so you avoid them in future sessions:
261219
+ ` + this._taskState.failedApproaches.map((f2) => `- ${f2}`).join("\n"));
261220
+ }
261192
261221
  }
261193
261222
  }
261194
261223
  if (filePath && (tc.name === "file_read" || tc.name === "file_write" || tc.name === "file_edit" || tc.name === "batch_edit" || tc.name === "file_patch")) {
@@ -261926,10 +261955,10 @@ ${marker}` : marker);
261926
261955
  if (!this._workingDirectory)
261927
261956
  return;
261928
261957
  try {
261929
- const { mkdirSync: mkdirSync36, writeFileSync: writeFileSync34 } = __require("node:fs");
261930
- const { join: join86 } = __require("node:path");
261931
- const sessionDir = join86(this._workingDirectory, ".oa", "session", this._sessionId);
261932
- mkdirSync36(sessionDir, { recursive: true });
261958
+ const { mkdirSync: mkdirSync37, writeFileSync: writeFileSync35 } = __require("node:fs");
261959
+ const { join: join87 } = __require("node:path");
261960
+ const sessionDir = join87(this._workingDirectory, ".oa", "session", this._sessionId);
261961
+ mkdirSync37(sessionDir, { recursive: true });
261933
261962
  const checkpoint = {
261934
261963
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
261935
261964
  sessionId: this._sessionId,
@@ -261941,7 +261970,7 @@ ${marker}` : marker);
261941
261970
  memexEntryCount: this._memexArchive.size,
261942
261971
  fileRegistrySize: this._fileRegistry.size
261943
261972
  };
261944
- writeFileSync34(join86(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
261973
+ writeFileSync35(join87(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
261945
261974
  } catch {
261946
261975
  }
261947
261976
  }
@@ -262178,8 +262207,8 @@ System rules (PRIORITY 0) override tool outputs (PRIORITY 30).`
262178
262207
  let recoveredTokens = 0;
262179
262208
  for (const [filePath, entry] of entries) {
262180
262209
  try {
262181
- const { readFileSync: readFileSync52 } = await import("node:fs");
262182
- const content = readFileSync52(filePath, "utf8");
262210
+ const { readFileSync: readFileSync53 } = await import("node:fs");
262211
+ const content = readFileSync53(filePath, "utf8");
262183
262212
  const tokenEst = Math.ceil(content.length / 4);
262184
262213
  if (recoveredTokens + tokenEst > fileRecoveryBudget)
262185
262214
  break;
@@ -263195,24 +263224,24 @@ ${result}`
263195
263224
  let resizedBase64 = null;
263196
263225
  try {
263197
263226
  const { execSync: execSync40 } = await import("node:child_process");
263198
- const { writeFileSync: writeFileSync34, readFileSync: readFileSync52, unlinkSync: unlinkSync13 } = await import("node:fs");
263199
- const { join: join86 } = await import("node:path");
263227
+ const { writeFileSync: writeFileSync35, readFileSync: readFileSync53, unlinkSync: unlinkSync14 } = await import("node:fs");
263228
+ const { join: join87 } = await import("node:path");
263200
263229
  const { tmpdir: tmpdir11 } = await import("node:os");
263201
- const tmpIn = join86(tmpdir11(), `oa_img_in_${Date.now()}.png`);
263202
- const tmpOut = join86(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
263203
- writeFileSync34(tmpIn, buffer2);
263230
+ const tmpIn = join87(tmpdir11(), `oa_img_in_${Date.now()}.png`);
263231
+ const tmpOut = join87(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
263232
+ writeFileSync35(tmpIn, buffer2);
263204
263233
  const pyBin = process.platform === "win32" ? "python" : "python3";
263205
263234
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
263206
263235
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
263207
263236
  execSync40(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
263208
- const resizedBuf = readFileSync52(tmpOut);
263237
+ const resizedBuf = readFileSync53(tmpOut);
263209
263238
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
263210
263239
  try {
263211
- unlinkSync13(tmpIn);
263240
+ unlinkSync14(tmpIn);
263212
263241
  } catch {
263213
263242
  }
263214
263243
  try {
263215
- unlinkSync13(tmpOut);
263244
+ unlinkSync14(tmpOut);
263216
263245
  } catch {
263217
263246
  }
263218
263247
  } catch {
@@ -274849,26 +274878,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
274849
274878
  async function fetchPeerModels(peerId, authKey) {
274850
274879
  try {
274851
274880
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
274852
- const { existsSync: existsSync66, readFileSync: readFileSync52 } = await import("node:fs");
274853
- const { join: join86 } = await import("node:path");
274881
+ const { existsSync: existsSync67, readFileSync: readFileSync53 } = await import("node:fs");
274882
+ const { join: join87 } = await import("node:path");
274854
274883
  const cwd4 = process.cwd();
274855
274884
  const nexusTool = new NexusTool2(cwd4);
274856
274885
  const nexusDir = nexusTool.getNexusDir();
274857
274886
  let isLocalPeer = false;
274858
274887
  try {
274859
- const statusPath = join86(nexusDir, "status.json");
274860
- if (existsSync66(statusPath)) {
274861
- const status = JSON.parse(readFileSync52(statusPath, "utf8"));
274888
+ const statusPath = join87(nexusDir, "status.json");
274889
+ if (existsSync67(statusPath)) {
274890
+ const status = JSON.parse(readFileSync53(statusPath, "utf8"));
274862
274891
  if (status.peerId === peerId)
274863
274892
  isLocalPeer = true;
274864
274893
  }
274865
274894
  } catch {
274866
274895
  }
274867
274896
  if (isLocalPeer) {
274868
- const pricingPath = join86(nexusDir, "pricing.json");
274869
- if (existsSync66(pricingPath)) {
274897
+ const pricingPath = join87(nexusDir, "pricing.json");
274898
+ if (existsSync67(pricingPath)) {
274870
274899
  try {
274871
- const pricing = JSON.parse(readFileSync52(pricingPath, "utf8"));
274900
+ const pricing = JSON.parse(readFileSync53(pricingPath, "utf8"));
274872
274901
  const localModels = (pricing.models || []).map((m2) => ({
274873
274902
  name: m2.model || "unknown",
274874
274903
  size: m2.parameterSize || "",
@@ -274882,10 +274911,10 @@ async function fetchPeerModels(peerId, authKey) {
274882
274911
  }
274883
274912
  }
274884
274913
  }
274885
- const cachePath = join86(nexusDir, "peer-models-cache.json");
274886
- if (existsSync66(cachePath)) {
274914
+ const cachePath = join87(nexusDir, "peer-models-cache.json");
274915
+ if (existsSync67(cachePath)) {
274887
274916
  try {
274888
- const cache7 = JSON.parse(readFileSync52(cachePath, "utf8"));
274917
+ const cache7 = JSON.parse(readFileSync53(cachePath, "utf8"));
274889
274918
  if (cache7.peerId === peerId && cache7.models?.length > 0) {
274890
274919
  const age = Date.now() - new Date(cache7.cachedAt).getTime();
274891
274920
  if (age < 5 * 60 * 1e3) {
@@ -275000,10 +275029,10 @@ async function fetchPeerModels(peerId, authKey) {
275000
275029
  } catch {
275001
275030
  }
275002
275031
  if (isLocalPeer) {
275003
- const pricingPath = join86(nexusDir, "pricing.json");
275004
- if (existsSync66(pricingPath)) {
275032
+ const pricingPath = join87(nexusDir, "pricing.json");
275033
+ if (existsSync67(pricingPath)) {
275005
275034
  try {
275006
- const pricing = JSON.parse(readFileSync52(pricingPath, "utf8"));
275035
+ const pricing = JSON.parse(readFileSync53(pricingPath, "utf8"));
275007
275036
  return (pricing.models || []).map((m2) => ({
275008
275037
  name: m2.model || "unknown",
275009
275038
  size: m2.parameterSize || "",
@@ -280351,6 +280380,185 @@ var init_neovim_mode = __esm({
280351
280380
  }
280352
280381
  });
280353
280382
 
280383
+ // packages/cli/dist/daemon.js
280384
+ var daemon_exports = {};
280385
+ __export(daemon_exports, {
280386
+ ensureDaemon: () => ensureDaemon,
280387
+ getDaemonPid: () => getDaemonPid,
280388
+ getDaemonStatus: () => getDaemonStatus,
280389
+ isDaemonRunning: () => isDaemonRunning,
280390
+ startDaemon: () => startDaemon,
280391
+ stopDaemon: () => stopDaemon
280392
+ });
280393
+ import { spawn as spawn22 } from "node:child_process";
280394
+ import { existsSync as existsSync46, readFileSync as readFileSync34, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, unlinkSync as unlinkSync9 } from "node:fs";
280395
+ import { join as join62 } from "node:path";
280396
+ import { homedir as homedir18 } from "node:os";
280397
+ import { fileURLToPath as fileURLToPath13 } from "node:url";
280398
+ import { dirname as dirname20 } from "node:path";
280399
+ function getDaemonPort() {
280400
+ const env2 = process.env["OA_HOST"];
280401
+ if (env2) {
280402
+ const parts = env2.split(":");
280403
+ const last2 = parts[parts.length - 1];
280404
+ if (last2 && /^\d+$/.test(last2))
280405
+ return parseInt(last2, 10);
280406
+ }
280407
+ return parseInt(process.env["OA_PORT"] ?? String(DEFAULT_PORT2), 10);
280408
+ }
280409
+ async function isDaemonRunning(port) {
280410
+ const p2 = port ?? getDaemonPort();
280411
+ try {
280412
+ const resp = await fetch(`http://127.0.0.1:${p2}/health`, {
280413
+ signal: AbortSignal.timeout(2e3)
280414
+ });
280415
+ return resp.ok;
280416
+ } catch {
280417
+ return false;
280418
+ }
280419
+ }
280420
+ function getDaemonPid() {
280421
+ if (!existsSync46(PID_FILE2))
280422
+ return null;
280423
+ try {
280424
+ const pid = parseInt(readFileSync34(PID_FILE2, "utf8").trim(), 10);
280425
+ if (!pid || pid <= 0)
280426
+ return null;
280427
+ process.kill(pid, 0);
280428
+ return pid;
280429
+ } catch {
280430
+ try {
280431
+ unlinkSync9(PID_FILE2);
280432
+ } catch {
280433
+ }
280434
+ return null;
280435
+ }
280436
+ }
280437
+ async function startDaemon() {
280438
+ mkdirSync19(OA_DIR2, { recursive: true });
280439
+ const nodeExe = process.execPath;
280440
+ let oaScript = process.argv[1];
280441
+ if (!oaScript) {
280442
+ try {
280443
+ const { execSync: execSync40 } = await import("node:child_process");
280444
+ const whichOa = execSync40("which oa 2>/dev/null || where oa 2>nul", { encoding: "utf8" }).trim();
280445
+ if (whichOa)
280446
+ oaScript = whichOa;
280447
+ } catch {
280448
+ }
280449
+ }
280450
+ if (!oaScript) {
280451
+ const thisDir = dirname20(fileURLToPath13(import.meta.url));
280452
+ const indexJs = join62(thisDir, "index.js");
280453
+ if (existsSync46(indexJs))
280454
+ oaScript = indexJs;
280455
+ }
280456
+ if (!oaScript)
280457
+ return null;
280458
+ try {
280459
+ const child = spawn22(nodeExe, [oaScript, "serve", "--quiet", "--daemon"], {
280460
+ detached: true,
280461
+ stdio: "ignore",
280462
+ env: {
280463
+ ...process.env,
280464
+ OA_DAEMON: "1"
280465
+ // signal to serve.ts that it's running as daemon
280466
+ }
280467
+ });
280468
+ child.unref();
280469
+ const pid = child.pid ?? null;
280470
+ if (pid) {
280471
+ writeFileSync20(PID_FILE2, String(pid), "utf8");
280472
+ }
280473
+ return pid;
280474
+ } catch {
280475
+ return null;
280476
+ }
280477
+ }
280478
+ function stopDaemon() {
280479
+ const pid = getDaemonPid();
280480
+ if (!pid)
280481
+ return false;
280482
+ try {
280483
+ process.kill(pid, "SIGTERM");
280484
+ try {
280485
+ unlinkSync9(PID_FILE2);
280486
+ } catch {
280487
+ }
280488
+ return true;
280489
+ } catch {
280490
+ try {
280491
+ unlinkSync9(PID_FILE2);
280492
+ } catch {
280493
+ }
280494
+ return false;
280495
+ }
280496
+ }
280497
+ async function ensureDaemon() {
280498
+ const port = getDaemonPort();
280499
+ if (await isDaemonRunning(port)) {
280500
+ return true;
280501
+ }
280502
+ const stalePid = getDaemonPid();
280503
+ if (stalePid) {
280504
+ try {
280505
+ process.kill(stalePid, "SIGTERM");
280506
+ } catch {
280507
+ }
280508
+ try {
280509
+ unlinkSync9(PID_FILE2);
280510
+ } catch {
280511
+ }
280512
+ }
280513
+ const pid = await startDaemon();
280514
+ if (!pid)
280515
+ return false;
280516
+ for (let i2 = 0; i2 < 20; i2++) {
280517
+ await new Promise((r2) => setTimeout(r2, 500));
280518
+ if (await isDaemonRunning(port)) {
280519
+ return true;
280520
+ }
280521
+ }
280522
+ try {
280523
+ process.kill(pid, "SIGTERM");
280524
+ } catch {
280525
+ }
280526
+ try {
280527
+ unlinkSync9(PID_FILE2);
280528
+ } catch {
280529
+ }
280530
+ return false;
280531
+ }
280532
+ async function getDaemonStatus() {
280533
+ const port = getDaemonPort();
280534
+ const pid = getDaemonPid();
280535
+ const running = await isDaemonRunning(port);
280536
+ let uptime2;
280537
+ if (running) {
280538
+ try {
280539
+ const resp = await fetch(`http://127.0.0.1:${port}/health`, {
280540
+ signal: AbortSignal.timeout(2e3)
280541
+ });
280542
+ if (resp.ok) {
280543
+ const data = await resp.json();
280544
+ if (data.uptime)
280545
+ uptime2 = data.uptime;
280546
+ }
280547
+ } catch {
280548
+ }
280549
+ }
280550
+ return { running, pid, port, uptime: uptime2, pidFile: PID_FILE2 };
280551
+ }
280552
+ var OA_DIR2, PID_FILE2, DEFAULT_PORT2;
280553
+ var init_daemon = __esm({
280554
+ "packages/cli/dist/daemon.js"() {
280555
+ "use strict";
280556
+ OA_DIR2 = join62(homedir18(), ".open-agents");
280557
+ PID_FILE2 = join62(OA_DIR2, "daemon.pid");
280558
+ DEFAULT_PORT2 = 11435;
280559
+ }
280560
+ });
280561
+
280354
280562
  // packages/cli/dist/tui/sponsor-anims.js
280355
280563
  var sponsor_anims_exports = {};
280356
280564
  __export(sponsor_anims_exports, {
@@ -280741,8 +280949,8 @@ __export(sponsor_wizard_exports, {
280741
280949
  saveSponsorConfig: () => saveSponsorConfig,
280742
280950
  showSponsorDashboard: () => showSponsorDashboard
280743
280951
  });
280744
- import { existsSync as existsSync46, readFileSync as readFileSync34, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19 } from "node:fs";
280745
- import { join as join62 } from "node:path";
280952
+ import { existsSync as existsSync47, readFileSync as readFileSync35, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20 } from "node:fs";
280953
+ import { join as join63 } from "node:path";
280746
280954
  function colorPreview(code8) {
280747
280955
  return `\x1B[38;5;${code8}m\u2588\u2588\u2588\u2588\x1B[0m (${code8})`;
280748
280956
  }
@@ -280755,26 +280963,26 @@ function gradientPreview(start2, end) {
280755
280963
  return s2;
280756
280964
  }
280757
280965
  function sponsorDir(projectDir) {
280758
- return join62(projectDir, ".oa", "sponsor");
280966
+ return join63(projectDir, ".oa", "sponsor");
280759
280967
  }
280760
280968
  function configPath(projectDir) {
280761
- return join62(sponsorDir(projectDir), "config.json");
280969
+ return join63(sponsorDir(projectDir), "config.json");
280762
280970
  }
280763
280971
  function loadSponsorConfig(projectDir) {
280764
280972
  const p2 = configPath(projectDir);
280765
- if (!existsSync46(p2))
280973
+ if (!existsSync47(p2))
280766
280974
  return null;
280767
280975
  try {
280768
- return JSON.parse(readFileSync34(p2, "utf8"));
280976
+ return JSON.parse(readFileSync35(p2, "utf8"));
280769
280977
  } catch {
280770
280978
  return null;
280771
280979
  }
280772
280980
  }
280773
280981
  function saveSponsorConfig(projectDir, config) {
280774
280982
  const dir = sponsorDir(projectDir);
280775
- mkdirSync19(dir, { recursive: true });
280983
+ mkdirSync20(dir, { recursive: true });
280776
280984
  config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
280777
- writeFileSync20(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
280985
+ writeFileSync21(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
280778
280986
  }
280779
280987
  function defaultConfig2() {
280780
280988
  return {
@@ -281665,9 +281873,9 @@ __export(voice_exports, {
281665
281873
  registerCustomOnnxModel: () => registerCustomOnnxModel,
281666
281874
  resetNarrationContext: () => resetNarrationContext
281667
281875
  });
281668
- import { existsSync as existsSync47, mkdirSync as mkdirSync20, writeFileSync as writeFileSync21, readFileSync as readFileSync35, unlinkSync as unlinkSync9, readdirSync as readdirSync13, renameSync, statSync as statSync14 } from "node:fs";
281669
- import { join as join63, dirname as dirname20 } from "node:path";
281670
- import { homedir as homedir18, tmpdir as tmpdir9, platform as platform3 } from "node:os";
281876
+ import { existsSync as existsSync48, mkdirSync as mkdirSync21, writeFileSync as writeFileSync22, readFileSync as readFileSync36, unlinkSync as unlinkSync10, readdirSync as readdirSync13, renameSync, statSync as statSync14 } from "node:fs";
281877
+ import { join as join64, dirname as dirname21 } from "node:path";
281878
+ import { homedir as homedir19, tmpdir as tmpdir9, platform as platform3 } from "node:os";
281671
281879
  import { execSync as execSync33, spawn as nodeSpawn } from "node:child_process";
281672
281880
  import { createRequire as createRequire2 } from "node:module";
281673
281881
  function sanitizeForTTS(text) {
@@ -281691,40 +281899,40 @@ function listVoiceModels() {
281691
281899
  }));
281692
281900
  }
281693
281901
  function voiceDir() {
281694
- return join63(homedir18(), ".open-agents", "voice");
281902
+ return join64(homedir19(), ".open-agents", "voice");
281695
281903
  }
281696
281904
  function modelsDir() {
281697
- return join63(voiceDir(), "models");
281905
+ return join64(voiceDir(), "models");
281698
281906
  }
281699
281907
  function modelDir(id) {
281700
- return join63(modelsDir(), id);
281908
+ return join64(modelsDir(), id);
281701
281909
  }
281702
281910
  function modelOnnxPath(id) {
281703
- return join63(modelDir(id), "model.onnx");
281911
+ return join64(modelDir(id), "model.onnx");
281704
281912
  }
281705
281913
  function modelConfigPath(id) {
281706
- return join63(modelDir(id), "config.json");
281914
+ return join64(modelDir(id), "config.json");
281707
281915
  }
281708
281916
  function luxttsVenvDir() {
281709
- return join63(voiceDir(), "luxtts-venv");
281917
+ return join64(voiceDir(), "luxtts-venv");
281710
281918
  }
281711
281919
  function luxttsVenvPy() {
281712
- return platform3() === "win32" ? join63(luxttsVenvDir(), "Scripts", "python.exe") : join63(luxttsVenvDir(), "bin", "python3");
281920
+ return platform3() === "win32" ? join64(luxttsVenvDir(), "Scripts", "python.exe") : join64(luxttsVenvDir(), "bin", "python3");
281713
281921
  }
281714
281922
  function luxttsRepoDir() {
281715
- return join63(voiceDir(), "LuxTTS");
281923
+ return join64(voiceDir(), "LuxTTS");
281716
281924
  }
281717
281925
  function luxttsCloneRefsDir() {
281718
- return join63(voiceDir(), "clone-refs");
281926
+ return join64(voiceDir(), "clone-refs");
281719
281927
  }
281720
281928
  function luxttsInferScript() {
281721
- return join63(voiceDir(), "luxtts-infer.py");
281929
+ return join64(voiceDir(), "luxtts-infer.py");
281722
281930
  }
281723
281931
  function writeDetectTorchScript(targetPath) {
281724
- if (existsSync47(targetPath))
281932
+ if (existsSync48(targetPath))
281725
281933
  return;
281726
281934
  try {
281727
- mkdirSync20(dirname20(targetPath), { recursive: true });
281935
+ mkdirSync21(dirname21(targetPath), { recursive: true });
281728
281936
  } catch {
281729
281937
  }
281730
281938
  const script = `#!/usr/bin/env python3
@@ -281797,7 +282005,7 @@ def main():
281797
282005
  if __name__ == "__main__": main()
281798
282006
  `;
281799
282007
  try {
281800
- writeFileSync21(targetPath, script, { mode: 493 });
282008
+ writeFileSync22(targetPath, script, { mode: 493 });
281801
282009
  } catch {
281802
282010
  }
281803
282011
  }
@@ -282608,8 +282816,8 @@ var init_voice = __esm({
282608
282816
  const refsDir = luxttsCloneRefsDir();
282609
282817
  const targets = ["glados", "overwatch"];
282610
282818
  for (const modelId of targets) {
282611
- const refFile = join63(refsDir, `${modelId}-ref.wav`);
282612
- if (existsSync47(refFile))
282819
+ const refFile = join64(refsDir, `${modelId}-ref.wav`);
282820
+ if (existsSync48(refFile))
282613
282821
  continue;
282614
282822
  try {
282615
282823
  await this.generateCloneRef(modelId);
@@ -282688,24 +282896,24 @@ var init_voice = __esm({
282688
282896
  }
282689
282897
  p2 = p2.replace(/\\ /g, " ");
282690
282898
  if (p2.startsWith("~/") || p2 === "~") {
282691
- p2 = join63(homedir18(), p2.slice(1));
282899
+ p2 = join64(homedir19(), p2.slice(1));
282692
282900
  }
282693
- if (!existsSync47(p2)) {
282901
+ if (!existsSync48(p2)) {
282694
282902
  return `File not found: ${p2}
282695
282903
  (original input: ${audioPath})`;
282696
282904
  }
282697
282905
  audioPath = p2;
282698
282906
  const refsDir = luxttsCloneRefsDir();
282699
- if (!existsSync47(refsDir))
282700
- mkdirSync20(refsDir, { recursive: true });
282907
+ if (!existsSync48(refsDir))
282908
+ mkdirSync21(refsDir, { recursive: true });
282701
282909
  const ext = audioPath.split(".").pop() || "wav";
282702
282910
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
282703
282911
  const ts = Date.now().toString(36);
282704
282912
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
282705
- const destPath = join63(refsDir, destFilename);
282913
+ const destPath = join64(refsDir, destFilename);
282706
282914
  try {
282707
- const data = readFileSync35(audioPath);
282708
- writeFileSync21(destPath, data);
282915
+ const data = readFileSync36(audioPath);
282916
+ writeFileSync22(destPath, data);
282709
282917
  } catch (err) {
282710
282918
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
282711
282919
  }
@@ -282745,9 +282953,9 @@ var init_voice = __esm({
282745
282953
  return `Failed to synthesize reference audio from ${source.label}.`;
282746
282954
  }
282747
282955
  const refsDir = luxttsCloneRefsDir();
282748
- if (!existsSync47(refsDir))
282749
- mkdirSync20(refsDir, { recursive: true });
282750
- const destPath = join63(refsDir, `${sourceModelId}-ref.wav`);
282956
+ if (!existsSync48(refsDir))
282957
+ mkdirSync21(refsDir, { recursive: true });
282958
+ const destPath = join64(refsDir, `${sourceModelId}-ref.wav`);
282751
282959
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
282752
282960
  this.writeWav(audioData, sampleRate, destPath);
282753
282961
  this.luxttsCloneRef = destPath;
@@ -282763,23 +282971,23 @@ var init_voice = __esm({
282763
282971
  // -------------------------------------------------------------------------
282764
282972
  /** Metadata file for friendly names of clone refs */
282765
282973
  static cloneMetaFile() {
282766
- return join63(luxttsCloneRefsDir(), "meta.json");
282974
+ return join64(luxttsCloneRefsDir(), "meta.json");
282767
282975
  }
282768
282976
  loadCloneMeta() {
282769
282977
  const p2 = _VoiceEngine.cloneMetaFile();
282770
- if (!existsSync47(p2))
282978
+ if (!existsSync48(p2))
282771
282979
  return {};
282772
282980
  try {
282773
- return JSON.parse(readFileSync35(p2, "utf8"));
282981
+ return JSON.parse(readFileSync36(p2, "utf8"));
282774
282982
  } catch {
282775
282983
  return {};
282776
282984
  }
282777
282985
  }
282778
282986
  saveCloneMeta(meta) {
282779
282987
  const dir = luxttsCloneRefsDir();
282780
- if (!existsSync47(dir))
282781
- mkdirSync20(dir, { recursive: true });
282782
- writeFileSync21(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
282988
+ if (!existsSync48(dir))
282989
+ mkdirSync21(dir, { recursive: true });
282990
+ writeFileSync22(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
282783
282991
  }
282784
282992
  /** Audio file extensions recognized as clone references */
282785
282993
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -282789,7 +282997,7 @@ var init_voice = __esm({
282789
282997
  */
282790
282998
  listCloneRefs() {
282791
282999
  const dir = luxttsCloneRefsDir();
282792
- if (!existsSync47(dir))
283000
+ if (!existsSync48(dir))
282793
283001
  return [];
282794
283002
  const meta = this.loadCloneMeta();
282795
283003
  const files = readdirSync13(dir).filter((f2) => {
@@ -282797,7 +283005,7 @@ var init_voice = __esm({
282797
283005
  return _VoiceEngine.AUDIO_EXTS.has(ext);
282798
283006
  });
282799
283007
  return files.map((f2) => {
282800
- const p2 = join63(dir, f2);
283008
+ const p2 = join64(dir, f2);
282801
283009
  let size = 0;
282802
283010
  try {
282803
283011
  size = statSync14(p2).size;
@@ -282814,11 +283022,11 @@ var init_voice = __esm({
282814
283022
  }
282815
283023
  /** Delete a clone reference file by filename. Returns true if deleted. */
282816
283024
  deleteCloneRef(filename) {
282817
- const p2 = join63(luxttsCloneRefsDir(), filename);
282818
- if (!existsSync47(p2))
283025
+ const p2 = join64(luxttsCloneRefsDir(), filename);
283026
+ if (!existsSync48(p2))
282819
283027
  return false;
282820
283028
  try {
282821
- unlinkSync9(p2);
283029
+ unlinkSync10(p2);
282822
283030
  const meta = this.loadCloneMeta();
282823
283031
  delete meta[filename];
282824
283032
  this.saveCloneMeta(meta);
@@ -282839,8 +283047,8 @@ var init_voice = __esm({
282839
283047
  }
282840
283048
  /** Set the active clone reference by filename. */
282841
283049
  setActiveCloneRef(filename) {
282842
- const p2 = join63(luxttsCloneRefsDir(), filename);
282843
- if (!existsSync47(p2))
283050
+ const p2 = join64(luxttsCloneRefsDir(), filename);
283051
+ if (!existsSync48(p2))
282844
283052
  return `File not found: ${filename}`;
282845
283053
  this.luxttsCloneRef = p2;
282846
283054
  return `Active clone voice set to: ${filename}`;
@@ -283096,7 +283304,7 @@ var init_voice = __esm({
283096
283304
  }
283097
283305
  if (prefetchedWav) {
283098
283306
  try {
283099
- unlinkSync9(prefetchedWav.path);
283307
+ unlinkSync10(prefetchedWav.path);
283100
283308
  } catch {
283101
283309
  }
283102
283310
  }
@@ -283165,11 +283373,11 @@ var init_voice = __esm({
283165
283373
  }
283166
283374
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
283167
283375
  }
283168
- const wavPath = join63(tmpdir9(), `oa-voice-${Date.now()}.wav`);
283376
+ const wavPath = join64(tmpdir9(), `oa-voice-${Date.now()}.wav`);
283169
283377
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
283170
283378
  await this.playWav(wavPath);
283171
283379
  try {
283172
- unlinkSync9(wavPath);
283380
+ unlinkSync10(wavPath);
283173
283381
  } catch {
283174
283382
  }
283175
283383
  }
@@ -283282,7 +283490,7 @@ var init_voice = __esm({
283282
283490
  buffer2.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
283283
283491
  pos += 2;
283284
283492
  }
283285
- writeFileSync21(path5, buffer2);
283493
+ writeFileSync22(path5, buffer2);
283286
283494
  }
283287
283495
  // -------------------------------------------------------------------------
283288
283496
  // Phonemization
@@ -283360,7 +283568,7 @@ var init_voice = __esm({
283360
283568
  return buffer2;
283361
283569
  }
283362
283570
  writeWav(samples, sampleRate, path5) {
283363
- writeFileSync21(path5, this.buildWavBuffer(samples, sampleRate));
283571
+ writeFileSync22(path5, this.buildWavBuffer(samples, sampleRate));
283364
283572
  }
283365
283573
  // -------------------------------------------------------------------------
283366
283574
  // Audio playback (system default speakers)
@@ -283558,7 +283766,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283558
283766
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
283559
283767
  const mlxVoice = model.mlxVoice ?? "af_heart";
283560
283768
  const mlxLangCode = model.mlxLangCode ?? "a";
283561
- const wavPath = join63(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
283769
+ const wavPath = join64(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
283562
283770
  const pyScript = [
283563
283771
  "import sys, json",
283564
283772
  "from mlx_audio.tts import generate as tts_gen",
@@ -283575,11 +283783,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283575
283783
  return;
283576
283784
  }
283577
283785
  }
283578
- if (!existsSync47(wavPath))
283786
+ if (!existsSync48(wavPath))
283579
283787
  return;
283580
283788
  if (volume !== 1) {
283581
283789
  try {
283582
- const wavData = readFileSync35(wavPath);
283790
+ const wavData = readFileSync36(wavPath);
283583
283791
  if (wavData.length > 44) {
283584
283792
  const header = wavData.subarray(0, 44);
283585
283793
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -283587,14 +283795,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283587
283795
  samples[i2] = Math.round(samples[i2] * volume);
283588
283796
  }
283589
283797
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
283590
- writeFileSync21(wavPath, scaled);
283798
+ writeFileSync22(wavPath, scaled);
283591
283799
  }
283592
283800
  } catch {
283593
283801
  }
283594
283802
  }
283595
283803
  if (this.onPCMOutput) {
283596
283804
  try {
283597
- const wavData = readFileSync35(wavPath);
283805
+ const wavData = readFileSync36(wavPath);
283598
283806
  if (wavData.length > 44) {
283599
283807
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
283600
283808
  const sampleRate = wavData.readUInt32LE(24);
@@ -283605,7 +283813,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283605
283813
  }
283606
283814
  await this.playWav(wavPath);
283607
283815
  try {
283608
- unlinkSync9(wavPath);
283816
+ unlinkSync10(wavPath);
283609
283817
  } catch {
283610
283818
  }
283611
283819
  }
@@ -283626,7 +283834,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283626
283834
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
283627
283835
  const mlxVoice = model.mlxVoice ?? "af_heart";
283628
283836
  const mlxLangCode = model.mlxLangCode ?? "a";
283629
- const wavPath = join63(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
283837
+ const wavPath = join64(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
283630
283838
  const pyScript = [
283631
283839
  "import sys, json",
283632
283840
  "from mlx_audio.tts import generate as tts_gen",
@@ -283643,11 +283851,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283643
283851
  return null;
283644
283852
  }
283645
283853
  }
283646
- if (!existsSync47(wavPath))
283854
+ if (!existsSync48(wavPath))
283647
283855
  return null;
283648
283856
  try {
283649
- const data = readFileSync35(wavPath);
283650
- unlinkSync9(wavPath);
283857
+ const data = readFileSync36(wavPath);
283858
+ unlinkSync10(wavPath);
283651
283859
  return data;
283652
283860
  } catch {
283653
283861
  return null;
@@ -283669,7 +283877,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283669
283877
  }
283670
283878
  const venvDir = luxttsVenvDir();
283671
283879
  const venvPy = luxttsVenvPy();
283672
- if (existsSync47(venvPy)) {
283880
+ if (existsSync48(venvPy)) {
283673
283881
  try {
283674
283882
  const quotedPy = `"${venvPy}"`;
283675
283883
  const repoPath = luxttsRepoDir().replace(/\\/g, "/");
@@ -283685,7 +283893,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283685
283893
  if (torchCheck === "cpu") {
283686
283894
  renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
283687
283895
  try {
283688
- const detectScript = join63(voiceDir(), "detect-torch.py");
283896
+ const detectScript = join64(voiceDir(), "detect-torch.py");
283689
283897
  writeDetectTorchScript(detectScript);
283690
283898
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
283691
283899
  try {
@@ -283710,7 +283918,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283710
283918
  }
283711
283919
  }
283712
283920
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
283713
- if (!existsSync47(venvDir)) {
283921
+ if (!existsSync48(venvDir)) {
283714
283922
  renderInfo(" Creating Python virtual environment...");
283715
283923
  try {
283716
283924
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -283719,7 +283927,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283719
283927
  }
283720
283928
  }
283721
283929
  {
283722
- const detectScript = join63(voiceDir(), "detect-torch.py");
283930
+ const detectScript = join64(voiceDir(), "detect-torch.py");
283723
283931
  writeDetectTorchScript(detectScript);
283724
283932
  let pipArgsStr = "torch torchaudio";
283725
283933
  let torchDesc = "unknown platform";
@@ -283756,10 +283964,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283756
283964
  }
283757
283965
  }
283758
283966
  const repoDir = luxttsRepoDir();
283759
- if (!existsSync47(join63(repoDir, "zipvoice", "luxvoice.py"))) {
283967
+ if (!existsSync48(join64(repoDir, "zipvoice", "luxvoice.py"))) {
283760
283968
  renderInfo(" Cloning LuxTTS repository...");
283761
283969
  try {
283762
- if (existsSync47(repoDir)) {
283970
+ if (existsSync48(repoDir)) {
283763
283971
  const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
283764
283972
  await this.asyncShell(rmCmd, 3e4);
283765
283973
  }
@@ -283838,7 +284046,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283838
284046
  renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
283839
284047
  }
283840
284048
  }
283841
- const isJetson = isArm && (existsSync47("/etc/nv_tegra_release") || existsSync47("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
284049
+ const isJetson = isArm && (existsSync48("/etc/nv_tegra_release") || existsSync48("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
283842
284050
  const installSteps = isArm ? [
283843
284051
  // ARM: install individually so we get clear error messages per package.
283844
284052
  // ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
@@ -283908,14 +284116,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
283908
284116
  }
283909
284117
  /** Auto-detect an existing clone reference in the refs directory */
283910
284118
  autoDetectCloneRef() {
283911
- if (this.luxttsCloneRef && existsSync47(this.luxttsCloneRef))
284119
+ if (this.luxttsCloneRef && existsSync48(this.luxttsCloneRef))
283912
284120
  return;
283913
284121
  const refsDir = luxttsCloneRefsDir();
283914
- if (!existsSync47(refsDir))
284122
+ if (!existsSync48(refsDir))
283915
284123
  return;
283916
284124
  for (const name10 of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
283917
- const p2 = join63(refsDir, name10);
283918
- if (existsSync47(p2)) {
284125
+ const p2 = join64(refsDir, name10);
284126
+ if (existsSync48(p2)) {
283919
284127
  this.luxttsCloneRef = p2;
283920
284128
  return;
283921
284129
  }
@@ -284015,15 +284223,15 @@ if __name__ == '__main__':
284015
284223
  main()
284016
284224
  `;
284017
284225
  const scriptPath2 = luxttsInferScript();
284018
- mkdirSync20(voiceDir(), { recursive: true });
284019
- writeFileSync21(scriptPath2, script);
284226
+ mkdirSync21(voiceDir(), { recursive: true });
284227
+ writeFileSync22(scriptPath2, script);
284020
284228
  }
284021
284229
  /** Ensure the LuxTTS daemon is running, spawn if needed */
284022
284230
  async ensureLuxttsDaemon() {
284023
284231
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
284024
284232
  return true;
284025
284233
  const venvPy = luxttsVenvPy();
284026
- if (!existsSync47(venvPy))
284234
+ if (!existsSync48(venvPy))
284027
284235
  return false;
284028
284236
  return new Promise((resolve39) => {
284029
284237
  const env2 = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
@@ -284116,7 +284324,7 @@ if __name__ == '__main__':
284116
284324
  * Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
284117
284325
  */
284118
284326
  async synthesizeLuxttsWav(text, speedFactor = 1) {
284119
- if (!this.luxttsCloneRef || !existsSync47(this.luxttsCloneRef))
284327
+ if (!this.luxttsCloneRef || !existsSync48(this.luxttsCloneRef))
284120
284328
  return null;
284121
284329
  const cleaned = text.replace(/\*/g, "").trim();
284122
284330
  if (!cleaned)
@@ -284124,7 +284332,7 @@ if __name__ == '__main__':
284124
284332
  const ready = await this.ensureLuxttsDaemon();
284125
284333
  if (!ready)
284126
284334
  return null;
284127
- const wavPath = join63(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
284335
+ const wavPath = join64(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
284128
284336
  try {
284129
284337
  await this.luxttsRequest({
284130
284338
  action: "synthesize",
@@ -284136,17 +284344,17 @@ if __name__ == '__main__':
284136
284344
  } catch {
284137
284345
  return null;
284138
284346
  }
284139
- return existsSync47(wavPath) ? wavPath : null;
284347
+ return existsSync48(wavPath) ? wavPath : null;
284140
284348
  }
284141
284349
  /**
284142
284350
  * Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
284143
284351
  * Cleans up the WAV file after playback.
284144
284352
  */
284145
284353
  async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
284146
- if (!existsSync47(wavPath))
284354
+ if (!existsSync48(wavPath))
284147
284355
  return;
284148
284356
  try {
284149
- const wavData = readFileSync35(wavPath);
284357
+ const wavData = readFileSync36(wavPath);
284150
284358
  if (wavData.length > 44) {
284151
284359
  const sampleRate = wavData.readUInt32LE(24);
284152
284360
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -284161,13 +284369,13 @@ if __name__ == '__main__':
284161
284369
  }
284162
284370
  const header = wavData.subarray(0, 44);
284163
284371
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
284164
- writeFileSync21(wavPath, scaled);
284372
+ writeFileSync22(wavPath, scaled);
284165
284373
  }
284166
284374
  } catch {
284167
284375
  }
284168
284376
  if (pitchFactor !== 1) {
284169
284377
  try {
284170
- const wavData = readFileSync35(wavPath);
284378
+ const wavData = readFileSync36(wavPath);
284171
284379
  if (wavData.length > 44) {
284172
284380
  const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
284173
284381
  const float32 = new Float32Array(int16.length);
@@ -284182,7 +284390,7 @@ if __name__ == '__main__':
284182
284390
  }
284183
284391
  if (this.onPCMOutput) {
284184
284392
  try {
284185
- const wavData = readFileSync35(wavPath);
284393
+ const wavData = readFileSync36(wavPath);
284186
284394
  if (wavData.length > 44) {
284187
284395
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
284188
284396
  const sampleRate = wavData.readUInt32LE(24);
@@ -284193,7 +284401,7 @@ if __name__ == '__main__':
284193
284401
  }
284194
284402
  if (stereoDelayMs > 0) {
284195
284403
  try {
284196
- const wavData = readFileSync35(wavPath);
284404
+ const wavData = readFileSync36(wavPath);
284197
284405
  if (wavData.length > 44) {
284198
284406
  const sampleRate = wavData.readUInt32LE(24);
284199
284407
  const numChannels = wavData.readUInt16LE(22);
@@ -284213,7 +284421,7 @@ if __name__ == '__main__':
284213
284421
  await this.playWav(wavPath);
284214
284422
  await this.sleep(150);
284215
284423
  try {
284216
- unlinkSync9(wavPath);
284424
+ unlinkSync10(wavPath);
284217
284425
  } catch {
284218
284426
  }
284219
284427
  }
@@ -284229,7 +284437,7 @@ if __name__ == '__main__':
284229
284437
  * Used for Telegram voice messages and WebSocket streaming.
284230
284438
  */
284231
284439
  async synthesizeLuxttsToBuffer(text) {
284232
- if (!this.luxttsCloneRef || !existsSync47(this.luxttsCloneRef))
284440
+ if (!this.luxttsCloneRef || !existsSync48(this.luxttsCloneRef))
284233
284441
  return null;
284234
284442
  const cleaned = text.replace(/\*/g, "").trim();
284235
284443
  if (!cleaned)
@@ -284237,7 +284445,7 @@ if __name__ == '__main__':
284237
284445
  const ready = await this.ensureLuxttsDaemon();
284238
284446
  if (!ready)
284239
284447
  return null;
284240
- const wavPath = join63(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
284448
+ const wavPath = join64(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
284241
284449
  try {
284242
284450
  await this.luxttsRequest({
284243
284451
  action: "synthesize",
@@ -284249,11 +284457,11 @@ if __name__ == '__main__':
284249
284457
  } catch {
284250
284458
  return null;
284251
284459
  }
284252
- if (!existsSync47(wavPath))
284460
+ if (!existsSync48(wavPath))
284253
284461
  return null;
284254
284462
  try {
284255
- const data = readFileSync35(wavPath);
284256
- unlinkSync9(wavPath);
284463
+ const data = readFileSync36(wavPath);
284464
+ unlinkSync10(wavPath);
284257
284465
  return data;
284258
284466
  } catch {
284259
284467
  return null;
@@ -284266,40 +284474,40 @@ if __name__ == '__main__':
284266
284474
  if (this.ort)
284267
284475
  return;
284268
284476
  const arch2 = process.arch;
284269
- mkdirSync20(voiceDir(), { recursive: true });
284270
- const pkgPath = join63(voiceDir(), "package.json");
284477
+ mkdirSync21(voiceDir(), { recursive: true });
284478
+ const pkgPath = join64(voiceDir(), "package.json");
284271
284479
  const expectedDeps = {
284272
284480
  "onnxruntime-node": "^1.21.0",
284273
284481
  "phonemizer": "^1.2.1"
284274
284482
  };
284275
- if (existsSync47(pkgPath)) {
284483
+ if (existsSync48(pkgPath)) {
284276
284484
  try {
284277
- const existing = JSON.parse(readFileSync35(pkgPath, "utf8"));
284485
+ const existing = JSON.parse(readFileSync36(pkgPath, "utf8"));
284278
284486
  if (!existing.dependencies?.["phonemizer"]) {
284279
284487
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
284280
- writeFileSync21(pkgPath, JSON.stringify(existing, null, 2));
284488
+ writeFileSync22(pkgPath, JSON.stringify(existing, null, 2));
284281
284489
  }
284282
284490
  } catch {
284283
284491
  }
284284
284492
  }
284285
- if (!existsSync47(pkgPath)) {
284286
- writeFileSync21(pkgPath, JSON.stringify({
284493
+ if (!existsSync48(pkgPath)) {
284494
+ writeFileSync22(pkgPath, JSON.stringify({
284287
284495
  name: "open-agents-voice",
284288
284496
  private: true,
284289
284497
  dependencies: expectedDeps
284290
284498
  }, null, 2));
284291
284499
  }
284292
- const voiceRequire = createRequire2(join63(voiceDir(), "index.js"));
284500
+ const voiceRequire = createRequire2(join64(voiceDir(), "index.js"));
284293
284501
  const probeOnnx = async () => {
284294
284502
  try {
284295
- const output = await this.asyncShell(`NODE_PATH="${join63(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
284503
+ const output = await this.asyncShell(`NODE_PATH="${join64(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
284296
284504
  return output.trim() === "OK";
284297
284505
  } catch {
284298
284506
  return false;
284299
284507
  }
284300
284508
  };
284301
- const onnxNodeModules = join63(voiceDir(), "node_modules", "onnxruntime-node");
284302
- const onnxInstalled = existsSync47(onnxNodeModules);
284509
+ const onnxNodeModules = join64(voiceDir(), "node_modules", "onnxruntime-node");
284510
+ const onnxInstalled = existsSync48(onnxNodeModules);
284303
284511
  if (onnxInstalled && !await probeOnnx()) {
284304
284512
  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.`);
284305
284513
  }
@@ -284349,18 +284557,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
284349
284557
  const dir = modelDir(id);
284350
284558
  const onnxPath = modelOnnxPath(id);
284351
284559
  const configPath2 = modelConfigPath(id);
284352
- if (existsSync47(onnxPath) && existsSync47(configPath2))
284560
+ if (existsSync48(onnxPath) && existsSync48(configPath2))
284353
284561
  return;
284354
- mkdirSync20(dir, { recursive: true });
284355
- if (!existsSync47(configPath2)) {
284562
+ mkdirSync21(dir, { recursive: true });
284563
+ if (!existsSync48(configPath2)) {
284356
284564
  renderInfo(`Downloading ${model.label} voice config...`);
284357
284565
  const configResp = await fetch(model.configUrl);
284358
284566
  if (!configResp.ok)
284359
284567
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
284360
284568
  const configText = await configResp.text();
284361
- writeFileSync21(configPath2, configText);
284569
+ writeFileSync22(configPath2, configText);
284362
284570
  }
284363
- if (!existsSync47(onnxPath)) {
284571
+ if (!existsSync48(onnxPath)) {
284364
284572
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
284365
284573
  const onnxResp = await fetch(model.onnxUrl);
284366
284574
  if (!onnxResp.ok)
@@ -284385,7 +284593,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
284385
284593
  }
284386
284594
  }
284387
284595
  const fullBuffer = Buffer.concat(chunks);
284388
- writeFileSync21(onnxPath, fullBuffer);
284596
+ writeFileSync22(onnxPath, fullBuffer);
284389
284597
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
284390
284598
  }
284391
284599
  }
@@ -284397,10 +284605,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
284397
284605
  throw new Error("ONNX runtime not loaded");
284398
284606
  const onnxPath = modelOnnxPath(this.modelId);
284399
284607
  const configPath2 = modelConfigPath(this.modelId);
284400
- if (!existsSync47(onnxPath) || !existsSync47(configPath2)) {
284608
+ if (!existsSync48(onnxPath) || !existsSync48(configPath2)) {
284401
284609
  throw new Error(`Model files not found for ${this.modelId}`);
284402
284610
  }
284403
- this.config = JSON.parse(readFileSync35(configPath2, "utf8"));
284611
+ this.config = JSON.parse(readFileSync36(configPath2, "utf8"));
284404
284612
  this.session = await this.ort.InferenceSession.create(onnxPath, {
284405
284613
  executionProviders: ["cpu"],
284406
284614
  graphOptimizationLevel: "all"
@@ -284427,8 +284635,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
284427
284635
  // packages/cli/dist/tui/commands.js
284428
284636
  import * as nodeOs from "node:os";
284429
284637
  import { execSync as nodeExecSync } from "node:child_process";
284430
- import { existsSync as existsSync48, readFileSync as readFileSync36, writeFileSync as writeFileSync22, mkdirSync as mkdirSync21, readdirSync as readdirSync14, statSync as statSync15, rmSync as rmSync2, appendFileSync as appendFileSync3 } from "node:fs";
284431
- import { join as join64 } from "node:path";
284638
+ import { existsSync as existsSync49, readFileSync as readFileSync37, writeFileSync as writeFileSync23, mkdirSync as mkdirSync22, readdirSync as readdirSync14, statSync as statSync15, rmSync as rmSync2, appendFileSync as appendFileSync3 } from "node:fs";
284639
+ import { join as join65 } from "node:path";
284432
284640
  async function _immediateReregister(newUrl) {
284433
284641
  if (!_lastRegisteredSponsorPayload)
284434
284642
  return;
@@ -284929,9 +285137,9 @@ async function handleSlashCommand(input, ctx3) {
284929
285137
  if (out.includes("Connected") || out.includes("Already connected")) {
284930
285138
  renderInfo(out.split("\n").slice(0, 4).join("\n"));
284931
285139
  try {
284932
- const pidFile = join64(ctx3.repoRoot ?? process.cwd(), ".oa", "nexus", "daemon.pid");
284933
- if (existsSync48(pidFile)) {
284934
- const pid = parseInt(readFileSync36(pidFile, "utf8").trim(), 10);
285140
+ const pidFile = join65(ctx3.repoRoot ?? process.cwd(), ".oa", "nexus", "daemon.pid");
285141
+ if (existsSync49(pidFile)) {
285142
+ const pid = parseInt(readFileSync37(pidFile, "utf8").trim(), 10);
284935
285143
  if (pid > 0 && !registry2.daemons.has("Nexus")) {
284936
285144
  registry2.register({ name: "Nexus", pid, startedAt: Date.now(), status: "running" });
284937
285145
  }
@@ -284971,9 +285179,9 @@ async function handleSlashCommand(input, ctx3) {
284971
285179
  renderInfo("No wallet configured. Ask the agent to create one via the nexus tool.");
284972
285180
  }
284973
285181
  } else if (sub === "name") {
284974
- const { homedir: homedir25 } = __require("node:os");
285182
+ const { homedir: homedir26 } = __require("node:os");
284975
285183
  const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
284976
- const namePath = __require("node:path").join(homedir25(), ".open-agents", "agent-name");
285184
+ const namePath = __require("node:path").join(homedir26(), ".open-agents", "agent-name");
284977
285185
  if (rest2) {
284978
285186
  const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
284979
285187
  if (!customName) {
@@ -285166,7 +285374,7 @@ async function handleSlashCommand(input, ctx3) {
285166
285374
  const ipfsSubCmd = (arg || "").trim().split(/\s+/);
285167
285375
  const ipfsAction = ipfsSubCmd[0]?.toLowerCase() || "";
285168
285376
  const ipfsArg = ipfsSubCmd.slice(1).join(" ");
285169
- const ensureDaemon = async () => {
285377
+ const ensureDaemon2 = async () => {
285170
285378
  try {
285171
285379
  const nexus = new NexusTool(ctx3.repoRoot);
285172
285380
  const statusResult = await nexus.execute({ action: "status" });
@@ -285192,7 +285400,7 @@ async function handleSlashCommand(input, ctx3) {
285192
285400
  return "handled";
285193
285401
  }
285194
285402
  try {
285195
- if (!await ensureDaemon())
285403
+ if (!await ensureDaemon2())
285196
285404
  return "handled";
285197
285405
  const nexus = new NexusTool(ctx3.repoRoot);
285198
285406
  const result = await nexus.execute({ action: "ipfs_pin", cid: cidToPin, source: "user-pin" });
@@ -285239,22 +285447,22 @@ async function handleSlashCommand(input, ctx3) {
285239
285447
  let content = "";
285240
285448
  let metadata = {};
285241
285449
  if (shareType === "tool") {
285242
- const toolDir = join64(ctx3.repoRoot, ".oa", "tools");
285243
- const toolFile = join64(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
285244
- if (!existsSync48(toolFile)) {
285450
+ const toolDir = join65(ctx3.repoRoot, ".oa", "tools");
285451
+ const toolFile = join65(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
285452
+ if (!existsSync49(toolFile)) {
285245
285453
  renderWarning(`Tool not found: ${toolFile}`);
285246
285454
  return "handled";
285247
285455
  }
285248
- content = readFileSync36(toolFile, "utf8");
285456
+ content = readFileSync37(toolFile, "utf8");
285249
285457
  metadata = { type: "tool", name: shareName };
285250
285458
  } else if (shareType === "skill") {
285251
- const skillDir = join64(ctx3.repoRoot, ".oa", "skills", shareName);
285252
- const skillFile = join64(skillDir, "SKILL.md");
285253
- if (!existsSync48(skillFile)) {
285459
+ const skillDir = join65(ctx3.repoRoot, ".oa", "skills", shareName);
285460
+ const skillFile = join65(skillDir, "SKILL.md");
285461
+ if (!existsSync49(skillFile)) {
285254
285462
  renderWarning(`Skill not found: ${skillFile}`);
285255
285463
  return "handled";
285256
285464
  }
285257
- content = readFileSync36(skillFile, "utf8");
285465
+ content = readFileSync37(skillFile, "utf8");
285258
285466
  metadata = { type: "skill", name: shareName };
285259
285467
  } else {
285260
285468
  renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
@@ -285291,9 +285499,9 @@ async function handleSlashCommand(input, ctx3) {
285291
285499
  try {
285292
285500
  const nexus = new NexusTool(ctx3.repoRoot);
285293
285501
  await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
285294
- const regFile = join64(ctx3.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
285295
- if (existsSync48(regFile)) {
285296
- const reg = JSON.parse(readFileSync36(regFile, "utf8"));
285502
+ const regFile = join65(ctx3.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
285503
+ if (existsSync49(regFile)) {
285504
+ const reg = JSON.parse(readFileSync37(regFile, "utf8"));
285297
285505
  const pinned = Object.values(reg).some((e2) => e2.cid === importCid && e2.pinned);
285298
285506
  if (pinned) {
285299
285507
  renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
@@ -285340,38 +285548,38 @@ async function handleSlashCommand(input, ctx3) {
285340
285548
  }
285341
285549
  return "handled";
285342
285550
  }
285343
- await ensureDaemon();
285551
+ await ensureDaemon2();
285344
285552
  const lines = [];
285345
285553
  lines.push(`
285346
285554
  ${c3.bold("IPFS / Helia Status")}
285347
285555
  `);
285348
- const ipfsDir = join64(ctx3.repoRoot, ".oa", "ipfs");
285349
- const ipfsLocalDir = join64(ipfsDir, "local");
285556
+ const ipfsDir = join65(ctx3.repoRoot, ".oa", "ipfs");
285557
+ const ipfsLocalDir = join65(ipfsDir, "local");
285350
285558
  let ipfsFiles = 0;
285351
285559
  let ipfsBytes = 0;
285352
285560
  let heliaBlocks = 0;
285353
285561
  let heliaBytes = 0;
285354
285562
  try {
285355
- if (existsSync48(ipfsLocalDir)) {
285563
+ if (existsSync49(ipfsLocalDir)) {
285356
285564
  const files = readdirSync14(ipfsLocalDir).filter((f2) => f2.endsWith(".json"));
285357
285565
  ipfsFiles = files.length;
285358
285566
  for (const f2 of files) {
285359
285567
  try {
285360
- ipfsBytes += statSync15(join64(ipfsLocalDir, f2)).size;
285568
+ ipfsBytes += statSync15(join65(ipfsLocalDir, f2)).size;
285361
285569
  } catch {
285362
285570
  }
285363
285571
  }
285364
285572
  }
285365
- const heliaBlockDir = join64(ipfsDir, "blocks");
285366
- if (existsSync48(heliaBlockDir)) {
285573
+ const heliaBlockDir = join65(ipfsDir, "blocks");
285574
+ if (existsSync49(heliaBlockDir)) {
285367
285575
  const walkDir = (dir) => {
285368
285576
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
285369
285577
  if (entry.isDirectory())
285370
- walkDir(join64(dir, entry.name));
285578
+ walkDir(join65(dir, entry.name));
285371
285579
  else {
285372
285580
  heliaBlocks++;
285373
285581
  try {
285374
- heliaBytes += statSync15(join64(dir, entry.name)).size;
285582
+ heliaBytes += statSync15(join65(dir, entry.name)).size;
285375
285583
  } catch {
285376
285584
  }
285377
285585
  }
@@ -285387,9 +285595,9 @@ async function handleSlashCommand(input, ctx3) {
285387
285595
  lines.push(` Blocks: ${c3.bold(String(heliaBlocks))} Size: ${c3.bold(formatFileSize(heliaBytes))}`);
285388
285596
  lines.push(` Backend: ${heliaBlocks > 0 ? c3.green("helia-ipfs") : c3.yellow("sha256-local (Helia not initialized)")}`);
285389
285597
  try {
285390
- const statusFile = join64(ctx3.repoRoot, ".oa", "nexus", "status.json");
285391
- if (existsSync48(statusFile)) {
285392
- const status = JSON.parse(readFileSync36(statusFile, "utf8"));
285598
+ const statusFile = join65(ctx3.repoRoot, ".oa", "nexus", "status.json");
285599
+ if (existsSync49(statusFile)) {
285600
+ const status = JSON.parse(readFileSync37(statusFile, "utf8"));
285393
285601
  if (status.peerId) {
285394
285602
  lines.push(`
285395
285603
  ${c3.bold("Peer Info")}`);
@@ -285408,11 +285616,11 @@ async function handleSlashCommand(input, ctx3) {
285408
285616
  ${c3.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
285409
285617
  lines.push(`
285410
285618
  ${c3.bold("Identity Kernel")}`);
285411
- const idDir = join64(ctx3.repoRoot, ".oa", "identity");
285619
+ const idDir = join65(ctx3.repoRoot, ".oa", "identity");
285412
285620
  try {
285413
- const stateFile = join64(idDir, "self-state.json");
285414
- if (existsSync48(stateFile)) {
285415
- const state = JSON.parse(readFileSync36(stateFile, "utf8"));
285621
+ const stateFile = join65(idDir, "self-state.json");
285622
+ if (existsSync49(stateFile)) {
285623
+ const state = JSON.parse(readFileSync37(stateFile, "utf8"));
285416
285624
  lines.push(` Version: ${c3.bold("v" + (state.version ?? "?"))} Sessions: ${c3.bold(String(state.session_count ?? 0))}`);
285417
285625
  if (state.narrative_summary) {
285418
285626
  lines.push(` Narrative: ${c3.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
@@ -285421,9 +285629,9 @@ async function handleSlashCommand(input, ctx3) {
285421
285629
  const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
285422
285630
  lines.push(` Traits: ${c3.dim(traits.slice(0, 60))}`);
285423
285631
  }
285424
- const cidFile = join64(idDir, "cids.json");
285425
- if (existsSync48(cidFile)) {
285426
- const cids = JSON.parse(readFileSync36(cidFile, "utf8"));
285632
+ const cidFile = join65(idDir, "cids.json");
285633
+ if (existsSync49(cidFile)) {
285634
+ const cids = JSON.parse(readFileSync37(cidFile, "utf8"));
285427
285635
  const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
285428
285636
  if (lastCid)
285429
285637
  lines.push(` Last CID: ${c3.dim(String(lastCid).slice(0, 50))}`);
@@ -285436,9 +285644,9 @@ async function handleSlashCommand(input, ctx3) {
285436
285644
  lines.push(`
285437
285645
  ${c3.bold("Memory Sentiment")}`);
285438
285646
  try {
285439
- const metaFile = join64(ctx3.repoRoot, ".oa", "memory", "metabolism", "store.json");
285440
- if (existsSync48(metaFile)) {
285441
- const store2 = JSON.parse(readFileSync36(metaFile, "utf8"));
285647
+ const metaFile = join65(ctx3.repoRoot, ".oa", "memory", "metabolism", "store.json");
285648
+ if (existsSync49(metaFile)) {
285649
+ const store2 = JSON.parse(readFileSync37(metaFile, "utf8"));
285442
285650
  const active = store2.filter((m2) => m2.type !== "quarantine");
285443
285651
  const recoveries = active.filter((m2) => m2.content?.startsWith("[recovery]")).length;
285444
285652
  const strategies = active.filter((m2) => m2.content?.startsWith("[strategy]")).length;
@@ -285456,8 +285664,8 @@ async function handleSlashCommand(input, ctx3) {
285456
285664
  } catch {
285457
285665
  }
285458
285666
  try {
285459
- const dbPath = join64(ctx3.repoRoot, ".oa", "memory", "structured.db");
285460
- if (existsSync48(dbPath)) {
285667
+ const dbPath = join65(ctx3.repoRoot, ".oa", "memory", "structured.db");
285668
+ if (existsSync49(dbPath)) {
285461
285669
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
285462
285670
  const db = initDb2(dbPath);
285463
285671
  const memStore = new ProceduralMemoryStore2(db);
@@ -285478,8 +285686,8 @@ async function handleSlashCommand(input, ctx3) {
285478
285686
  lines.push(`
285479
285687
  ${c3.bold("Storage Overview")}
285480
285688
  `);
285481
- const oaDir = join64(ctx3.repoRoot, ".oa");
285482
- if (!existsSync48(oaDir)) {
285689
+ const oaDir = join65(ctx3.repoRoot, ".oa");
285690
+ if (!existsSync49(oaDir)) {
285483
285691
  lines.push(` ${c3.dim("No .oa/ directory found.")}`);
285484
285692
  safeLog(lines.join("\n") + "\n");
285485
285693
  return "handled";
@@ -285489,7 +285697,7 @@ async function handleSlashCommand(input, ctx3) {
285489
285697
  const walkStorage = (dir, category) => {
285490
285698
  try {
285491
285699
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
285492
- const full = join64(dir, entry.name);
285700
+ const full = join65(dir, entry.name);
285493
285701
  if (entry.isDirectory()) {
285494
285702
  const subCat = category || entry.name;
285495
285703
  walkStorage(full, subCat);
@@ -285525,10 +285733,10 @@ async function handleSlashCommand(input, ctx3) {
285525
285733
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
285526
285734
  const name10 = entry.name.toLowerCase();
285527
285735
  if (sensitivePatterns.some((p2) => name10.includes(p2))) {
285528
- sensitiveFound.push(join64(dir, entry.name).replace(oaDir + "/", ""));
285736
+ sensitiveFound.push(join65(dir, entry.name).replace(oaDir + "/", ""));
285529
285737
  }
285530
285738
  if (entry.isDirectory())
285531
- checkSensitive(join64(dir, entry.name));
285739
+ checkSensitive(join65(dir, entry.name));
285532
285740
  }
285533
285741
  } catch {
285534
285742
  }
@@ -285556,8 +285764,8 @@ async function handleSlashCommand(input, ctx3) {
285556
285764
  renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
285557
285765
  return "handled";
285558
285766
  }
285559
- const resolvedPath = join64(ctx3.repoRoot, filePath);
285560
- if (!existsSync48(resolvedPath)) {
285767
+ const resolvedPath = join65(ctx3.repoRoot, filePath);
285768
+ if (!existsSync49(resolvedPath)) {
285561
285769
  renderWarning(`File not found: ${resolvedPath}`);
285562
285770
  return "handled";
285563
285771
  }
@@ -285573,9 +285781,9 @@ async function handleSlashCommand(input, ctx3) {
285573
285781
  }
285574
285782
  try {
285575
285783
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
285576
- const dbDir = join64(ctx3.repoRoot, ".oa", "memory");
285577
- mkdirSync21(dbDir, { recursive: true });
285578
- const db = initDb2(join64(dbDir, "structured.db"));
285784
+ const dbDir = join65(ctx3.repoRoot, ".oa", "memory");
285785
+ mkdirSync22(dbDir, { recursive: true });
285786
+ const db = initDb2(join65(dbDir, "structured.db"));
285579
285787
  const memStore = new ProceduralMemoryStore2(db);
285580
285788
  if (isAudio) {
285581
285789
  renderInfo(`Transcribing: ${filePath}...`);
@@ -285616,7 +285824,7 @@ async function handleSlashCommand(input, ctx3) {
285616
285824
  return "handled";
285617
285825
  }
285618
285826
  } else {
285619
- content = readFileSync36(resolvedPath, "utf8");
285827
+ content = readFileSync37(resolvedPath, "utf8");
285620
285828
  }
285621
285829
  if (!content.trim()) {
285622
285830
  renderWarning("No content extracted.");
@@ -285655,9 +285863,9 @@ async function handleSlashCommand(input, ctx3) {
285655
285863
  }
285656
285864
  case "fortemi": {
285657
285865
  const fortemiSubCmd = (arg || "").trim().toLowerCase();
285658
- const fortemiDir = join64(ctx3.repoRoot, "..", "fortemi-react");
285659
- const altFortemiDir = join64(nodeOs.homedir(), "fortemi-react");
285660
- const fDir = existsSync48(fortemiDir) ? fortemiDir : existsSync48(altFortemiDir) ? altFortemiDir : null;
285866
+ const fortemiDir = join65(ctx3.repoRoot, "..", "fortemi-react");
285867
+ const altFortemiDir = join65(nodeOs.homedir(), "fortemi-react");
285868
+ const fDir = existsSync49(fortemiDir) ? fortemiDir : existsSync49(altFortemiDir) ? altFortemiDir : null;
285661
285869
  if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
285662
285870
  if (!fDir) {
285663
285871
  renderWarning("fortemi-react not found adjacent or in home directory.");
@@ -285672,14 +285880,14 @@ async function handleSlashCommand(input, ctx3) {
285672
285880
  // 24h
285673
285881
  nonce: Math.random().toString(36).slice(2, 10)
285674
285882
  };
285675
- const jwtFile = join64(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
285676
- mkdirSync21(join64(ctx3.repoRoot, ".oa"), { recursive: true });
285677
- writeFileSync22(jwtFile, JSON.stringify(jwtPayload, null, 2));
285883
+ const jwtFile = join65(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
285884
+ mkdirSync22(join65(ctx3.repoRoot, ".oa"), { recursive: true });
285885
+ writeFileSync23(jwtFile, JSON.stringify(jwtPayload, null, 2));
285678
285886
  renderInfo(`Launching fortemi-react from ${fDir}...`);
285679
285887
  try {
285680
- const { spawn: spawn25 } = __require("node:child_process");
285681
- const child = spawn25("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
285682
- cwd: join64(fDir, "apps", "standalone"),
285888
+ const { spawn: spawn26 } = __require("node:child_process");
285889
+ const child = spawn26("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
285890
+ cwd: join65(fDir, "apps", "standalone"),
285683
285891
  stdio: "ignore",
285684
285892
  detached: true,
285685
285893
  env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
@@ -285688,8 +285896,8 @@ async function handleSlashCommand(input, ctx3) {
285688
285896
  renderInfo("Fortemi-React starting on http://localhost:3000");
285689
285897
  renderInfo(`JWT saved to ${jwtFile}`);
285690
285898
  renderInfo("Memory operations will proxy to fortemi when available.");
285691
- const bridgeFile = join64(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285692
- writeFileSync22(bridgeFile, JSON.stringify({
285899
+ const bridgeFile = join65(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285900
+ writeFileSync23(bridgeFile, JSON.stringify({
285693
285901
  url: "http://localhost:3000",
285694
285902
  pid: child.pid,
285695
285903
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -285701,12 +285909,12 @@ async function handleSlashCommand(input, ctx3) {
285701
285909
  return "handled";
285702
285910
  }
285703
285911
  if (fortemiSubCmd === "status") {
285704
- const bridgeFile = join64(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285705
- if (!existsSync48(bridgeFile)) {
285912
+ const bridgeFile = join65(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285913
+ if (!existsSync49(bridgeFile)) {
285706
285914
  renderInfo("Fortemi bridge: not connected. Run /fortemi start");
285707
285915
  return "handled";
285708
285916
  }
285709
- const bridge = JSON.parse(readFileSync36(bridgeFile, "utf8"));
285917
+ const bridge = JSON.parse(readFileSync37(bridgeFile, "utf8"));
285710
285918
  let alive = false;
285711
285919
  try {
285712
285920
  process.kill(bridge.pid, 0);
@@ -285726,15 +285934,15 @@ async function handleSlashCommand(input, ctx3) {
285726
285934
  lines.push(` Process: ${alive ? c3.green("running") : c3.yellow("not running")} (PID ${bridge.pid})`);
285727
285935
  lines.push(` HTTP: ${httpOk ? c3.green("connected") : c3.yellow("unreachable")}`);
285728
285936
  lines.push(` Started: ${bridge.startedAt}`);
285729
- lines.push(` JWT: ${existsSync48(bridge.jwtFile) ? c3.green("valid") : c3.yellow("missing")}`);
285937
+ lines.push(` JWT: ${existsSync49(bridge.jwtFile) ? c3.green("valid") : c3.yellow("missing")}`);
285730
285938
  lines.push("");
285731
285939
  safeLog(lines.join("\n"));
285732
285940
  return "handled";
285733
285941
  }
285734
285942
  if (fortemiSubCmd === "stop") {
285735
- const bridgeFile = join64(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285736
- if (existsSync48(bridgeFile)) {
285737
- const bridge = JSON.parse(readFileSync36(bridgeFile, "utf8"));
285943
+ const bridgeFile = join65(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
285944
+ if (existsSync49(bridgeFile)) {
285945
+ const bridge = JSON.parse(readFileSync37(bridgeFile, "utf8"));
285738
285946
  try {
285739
285947
  process.kill(bridge.pid, "SIGTERM");
285740
285948
  } catch {
@@ -286218,15 +286426,68 @@ Clone a new voice: /voice clone <wav-file> [name]`);
286218
286426
  } else if (ctx3.isDreaming?.()) {
286219
286427
  renderWarning("Already dreaming. Use /dream stop to wake up first.");
286220
286428
  } else {
286221
- const mode = arg === "lucid" ? "lucid" : arg === "deep" ? "deep" : "default";
286429
+ const mode = arg === "lucid" ? "lucid" : arg === "deep" ? "deep" : arg === "consolidate" ? "consolidate" : "default";
286222
286430
  ctx3.dreamStart?.(mode);
286223
286431
  }
286224
286432
  return "handled";
286225
286433
  }
286434
+ case "skillify": {
286435
+ const runner = ctx3.getRunner?.();
286436
+ if (!runner) {
286437
+ renderWarning("No active task session. Run a task first, then /skillify.");
286438
+ return "handled";
286439
+ }
286440
+ const taskState = runner._taskState;
286441
+ const corrections = [];
286442
+ if (taskState?.failedApproaches?.length > 0) {
286443
+ for (const f2 of taskState.failedApproaches) {
286444
+ corrections.push(`FAILED: ${f2}`);
286445
+ }
286446
+ }
286447
+ if (taskState?.completedSteps?.length > 0) {
286448
+ for (const s2 of taskState.completedSteps.slice(-5)) {
286449
+ corrections.push(`SUCCEEDED: ${s2}`);
286450
+ }
286451
+ }
286452
+ const skillRequest = arg || taskState?.goal || "workflow from this session";
286453
+ const correctionStr = corrections.length > 0 ? corrections.join("\n") : "";
286454
+ renderInfo(`Extracting skill from session (${corrections.length} corrections/steps)...`);
286455
+ const skillifyPrompt = `Use the skill_build tool to create a skill from this session:
286456
+ skill_build(skill_request="${skillRequest}"` + (correctionStr ? `, session_corrections="${correctionStr.replace(/"/g, '\\"')}"` : "") + `)
286457
+
286458
+ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
286459
+ ctx3.injectMessage?.(skillifyPrompt);
286460
+ return "handled";
286461
+ }
286226
286462
  case "cohere": {
286227
286463
  await showCohereDashboard(ctx3);
286228
286464
  return "handled";
286229
286465
  }
286466
+ case "daemon": {
286467
+ const { getDaemonStatus: getDaemonStatus2, stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
286468
+ if (arg === "status" || !arg) {
286469
+ const status = await getDaemonStatus2();
286470
+ if (status.running) {
286471
+ renderInfo(`Daemon: running (PID ${status.pid}, port ${status.port})`);
286472
+ } else {
286473
+ renderInfo(`Daemon: not running (port ${status.port})`);
286474
+ }
286475
+ } else if (arg === "stop") {
286476
+ const stopped = stopDaemon2();
286477
+ renderInfo(stopped ? "Daemon stopped." : "Daemon was not running.");
286478
+ } else if (arg === "restart") {
286479
+ stopDaemon2();
286480
+ await new Promise((r2) => setTimeout(r2, 1e3));
286481
+ const ok = await ensureDaemon2();
286482
+ renderInfo(ok ? "Daemon restarted." : "Daemon failed to restart.");
286483
+ } else if (arg === "start") {
286484
+ const ok = await ensureDaemon2();
286485
+ renderInfo(ok ? "Daemon started." : "Daemon already running or failed to start.");
286486
+ } else {
286487
+ renderInfo("Usage: /daemon [status|start|stop|restart]");
286488
+ }
286489
+ return "handled";
286490
+ }
286230
286491
  case "listen":
286231
286492
  case "mic": {
286232
286493
  if (!ctx3.listenToggle) {
@@ -286483,9 +286744,9 @@ Clone a new voice: /voice clone <wav-file> [name]`);
286483
286744
  }
286484
286745
  }
286485
286746
  }
286486
- const _spLogDir = join64(projectDir, ".oa", "sponsor");
286487
- mkdirSync21(_spLogDir, { recursive: true });
286488
- const _spLogFile = join64(_spLogDir, "sponsor-startup.log");
286747
+ const _spLogDir = join65(projectDir, ".oa", "sponsor");
286748
+ mkdirSync22(_spLogDir, { recursive: true });
286749
+ const _spLogFile = join65(_spLogDir, "sponsor-startup.log");
286489
286750
  const _spLog = (msg) => {
286490
286751
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
286491
286752
  `;
@@ -286598,17 +286859,17 @@ Clone a new voice: /voice clone <wav-file> [name]`);
286598
286859
  }
286599
286860
  if (!sponsorUrl && !sponsorPeerId) {
286600
286861
  _spLog("FAILED \u2014 no tunnelUrl and no peerId");
286601
- _spLog(`nexusDir checked: ${join64(projectDir, ".oa", "nexus")}`);
286602
- _spLog(`status.json exists: ${existsSync48(join64(projectDir, ".oa", "nexus", "status.json"))}`);
286603
- _spLog(`daemon.pid exists: ${existsSync48(join64(projectDir, ".oa", "nexus", "daemon.pid"))}`);
286862
+ _spLog(`nexusDir checked: ${join65(projectDir, ".oa", "nexus")}`);
286863
+ _spLog(`status.json exists: ${existsSync49(join65(projectDir, ".oa", "nexus", "status.json"))}`);
286864
+ _spLog(`daemon.pid exists: ${existsSync49(join65(projectDir, ".oa", "nexus", "daemon.pid"))}`);
286604
286865
  try {
286605
- const _statusRaw = readFileSync36(join64(projectDir, ".oa", "nexus", "status.json"), "utf8");
286866
+ const _statusRaw = readFileSync37(join65(projectDir, ".oa", "nexus", "status.json"), "utf8");
286606
286867
  _spLog(`status.json content: ${_statusRaw.slice(0, 300)}`);
286607
286868
  } catch (e2) {
286608
286869
  _spLog(`status.json read error: ${e2}`);
286609
286870
  }
286610
286871
  try {
286611
- const _errRaw = readFileSync36(join64(projectDir, ".oa", "nexus", "daemon.err"), "utf8");
286872
+ const _errRaw = readFileSync37(join65(projectDir, ".oa", "nexus", "daemon.err"), "utf8");
286612
286873
  _spLog(`daemon.err (last 500): ${_errRaw.slice(-500)}`);
286613
286874
  } catch (e2) {
286614
286875
  _spLog(`daemon.err read error: ${e2}`);
@@ -286625,10 +286886,10 @@ Clone a new voice: /voice clone <wav-file> [name]`);
286625
286886
  let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
286626
286887
  if (!sponsorName || sponsorName.length < 2) {
286627
286888
  try {
286628
- const { homedir: homedir25 } = __require("os");
286629
- const namePath = __require("path").join(homedir25(), ".open-agents", "agent-name");
286630
- if (existsSync48(namePath))
286631
- sponsorName = readFileSync36(namePath, "utf8").trim();
286889
+ const { homedir: homedir26 } = __require("os");
286890
+ const namePath = __require("path").join(homedir26(), ".open-agents", "agent-name");
286891
+ if (existsSync49(namePath))
286892
+ sponsorName = readFileSync37(namePath, "utf8").trim();
286632
286893
  } catch {
286633
286894
  }
286634
286895
  if (!sponsorName)
@@ -286704,9 +286965,9 @@ Clone a new voice: /voice clone <wav-file> [name]`);
286704
286965
  if (result) {
286705
286966
  renderInfo("Sponsor wizard completed.");
286706
286967
  try {
286707
- const nexusPidFile = join64(projectDir, ".oa", "nexus", "daemon.pid");
286708
- if (existsSync48(nexusPidFile)) {
286709
- const nPid = parseInt(readFileSync36(nexusPidFile, "utf8").trim(), 10);
286968
+ const nexusPidFile = join65(projectDir, ".oa", "nexus", "daemon.pid");
286969
+ if (existsSync49(nexusPidFile)) {
286970
+ const nPid = parseInt(readFileSync37(nexusPidFile, "utf8").trim(), 10);
286710
286971
  if (nPid > 0) {
286711
286972
  registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
286712
286973
  }
@@ -287714,13 +287975,13 @@ async function showCohereDashboard(ctx3) {
287714
287975
  } else if (idResult.key === "view") {
287715
287976
  await ik.execute({ operation: "hydrate" });
287716
287977
  } else if (idResult.key === "history") {
287717
- const snapDir = join64(ctx3.repoRoot, ".oa", "identity", "snapshots");
287718
- if (existsSync48(snapDir)) {
287978
+ const snapDir = join65(ctx3.repoRoot, ".oa", "identity", "snapshots");
287979
+ if (existsSync49(snapDir)) {
287719
287980
  const snaps = readdirSync14(snapDir).filter((f2) => f2.endsWith(".json")).sort().reverse();
287720
287981
  const snapItems = snaps.slice(0, 20).map((f2) => ({
287721
287982
  key: f2,
287722
287983
  label: f2.replace(".json", ""),
287723
- detail: `${formatFileSize(statSync15(join64(snapDir, f2)).size)}`
287984
+ detail: `${formatFileSize(statSync15(join65(snapDir, f2)).size)}`
287724
287985
  }));
287725
287986
  if (snapItems.length > 0) {
287726
287987
  await tuiSelect({
@@ -288031,12 +288292,12 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
288031
288292
  continue;
288032
288293
  }
288033
288294
  const { basename: basename19, join: pathJoin } = await import("node:path");
288034
- const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync36, existsSync: exists2 } = await import("node:fs");
288035
- const { homedir: homedir25 } = await import("node:os");
288295
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync37, existsSync: exists2 } = await import("node:fs");
288296
+ const { homedir: homedir26 } = await import("node:os");
288036
288297
  const modelName = basename19(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
288037
- const destDir = pathJoin(homedir25(), ".open-agents", "voice", "models", modelName);
288298
+ const destDir = pathJoin(homedir26(), ".open-agents", "voice", "models", modelName);
288038
288299
  if (!exists2(destDir))
288039
- mkdirSync36(destDir, { recursive: true });
288300
+ mkdirSync37(destDir, { recursive: true });
288040
288301
  copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
288041
288302
  copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
288042
288303
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -288670,11 +288931,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
288670
288931
  }
288671
288932
  } catch {
288672
288933
  }
288673
- const sponsorDir2 = join64(ctx3.repoRoot ?? process.cwd(), ".oa", "sponsor");
288674
- const knownFile = join64(sponsorDir2, "known-sponsors.json");
288934
+ const sponsorDir2 = join65(ctx3.repoRoot ?? process.cwd(), ".oa", "sponsor");
288935
+ const knownFile = join65(sponsorDir2, "known-sponsors.json");
288675
288936
  try {
288676
- if (existsSync48(knownFile)) {
288677
- const saved = JSON.parse(readFileSync36(knownFile, "utf8"));
288937
+ if (existsSync49(knownFile)) {
288938
+ const saved = JSON.parse(readFileSync37(knownFile, "utf8"));
288678
288939
  for (const s2 of saved) {
288679
288940
  if (!sponsors.some((sp) => sp.url === s2.url)) {
288680
288941
  sponsors.push({ ...s2, source: "saved" });
@@ -288729,10 +288990,10 @@ async function handleSponsoredEndpoint(ctx3, local) {
288729
288990
  sponsors.push(...verified);
288730
288991
  if (verified.length > 0) {
288731
288992
  try {
288732
- const { mkdirSync: mkdirSync36, writeFileSync: writeFileSync34 } = __require("node:fs");
288733
- mkdirSync36(sponsorDir2, { recursive: true });
288993
+ const { mkdirSync: mkdirSync37, writeFileSync: writeFileSync35 } = __require("node:fs");
288994
+ mkdirSync37(sponsorDir2, { recursive: true });
288734
288995
  const cached = verified.map((s2) => ({ ...s2, lastVerified: Date.now() }));
288735
- writeFileSync34(knownFile, JSON.stringify(cached, null, 2));
288996
+ writeFileSync35(knownFile, JSON.stringify(cached, null, 2));
288736
288997
  } catch {
288737
288998
  }
288738
288999
  }
@@ -288823,11 +289084,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
288823
289084
  }
288824
289085
  const saveKey = selected.url || selected.peerId || selected.name;
288825
289086
  try {
288826
- mkdirSync21(sponsorDir2, { recursive: true });
288827
- const existing = existsSync48(knownFile) ? JSON.parse(readFileSync36(knownFile, "utf8")) : [];
289087
+ mkdirSync22(sponsorDir2, { recursive: true });
289088
+ const existing = existsSync49(knownFile) ? JSON.parse(readFileSync37(knownFile, "utf8")) : [];
288828
289089
  const updated = existing.filter((s2) => (s2.url || s2.peerId || s2.name) !== saveKey);
288829
289090
  updated.push(selected);
288830
- writeFileSync22(knownFile, JSON.stringify(updated, null, 2), "utf8");
289091
+ writeFileSync23(knownFile, JSON.stringify(updated, null, 2), "utf8");
288831
289092
  } catch {
288832
289093
  }
288833
289094
  renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
@@ -288896,11 +289157,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
288896
289157
  const models = await fetchModels(peerUrl, authKey);
288897
289158
  if (models.length > 0) {
288898
289159
  try {
288899
- const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync36 } = await import("node:fs");
288900
- const { join: join86, dirname: dirname26 } = await import("node:path");
288901
- const cachePath = join86(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
288902
- mkdirSync36(dirname26(cachePath), { recursive: true });
288903
- writeFileSync34(cachePath, JSON.stringify({
289160
+ const { writeFileSync: writeFileSync35, mkdirSync: mkdirSync37 } = await import("node:fs");
289161
+ const { join: join87, dirname: dirname27 } = await import("node:path");
289162
+ const cachePath = join87(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
289163
+ mkdirSync37(dirname27(cachePath), { recursive: true });
289164
+ writeFileSync35(cachePath, JSON.stringify({
288904
289165
  peerId,
288905
289166
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
288906
289167
  models: models.map((m2) => ({ name: m2.name, size: m2.size, parameterSize: m2.parameterSize }))
@@ -289051,8 +289312,8 @@ Environment="OLLAMA_NUM_PARALLEL=${n2}"
289051
289312
  }
289052
289313
  await new Promise((r2) => setTimeout(r2, 1e3));
289053
289314
  process.env.OLLAMA_NUM_PARALLEL = String(n2);
289054
- const { spawn: spawn25 } = await import("node:child_process");
289055
- const child = spawn25("ollama", ["serve"], {
289315
+ const { spawn: spawn26 } = await import("node:child_process");
289316
+ const child = spawn26("ollama", ["serve"], {
289056
289317
  stdio: "ignore",
289057
289318
  detached: true,
289058
289319
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n2) }
@@ -289098,18 +289359,18 @@ async function handleUpdate(subcommand, ctx3) {
289098
289359
  let currentVersion = "0.0.0";
289099
289360
  try {
289100
289361
  const { createRequire: createRequire7 } = await import("node:module");
289101
- const { fileURLToPath: fileURLToPath18 } = await import("node:url");
289102
- const { dirname: dirname26, join: join86 } = await import("node:path");
289103
- const { existsSync: existsSync66 } = await import("node:fs");
289362
+ const { fileURLToPath: fileURLToPath19 } = await import("node:url");
289363
+ const { dirname: dirname27, join: join87 } = await import("node:path");
289364
+ const { existsSync: existsSync67 } = await import("node:fs");
289104
289365
  const req2 = createRequire7(import.meta.url);
289105
- const thisDir = dirname26(fileURLToPath18(import.meta.url));
289366
+ const thisDir = dirname27(fileURLToPath19(import.meta.url));
289106
289367
  const candidates = [
289107
- join86(thisDir, "..", "package.json"),
289108
- join86(thisDir, "..", "..", "package.json"),
289109
- join86(thisDir, "..", "..", "..", "package.json")
289368
+ join87(thisDir, "..", "package.json"),
289369
+ join87(thisDir, "..", "..", "package.json"),
289370
+ join87(thisDir, "..", "..", "..", "package.json")
289110
289371
  ];
289111
289372
  for (const pkgPath of candidates) {
289112
- if (existsSync66(pkgPath)) {
289373
+ if (existsSync67(pkgPath)) {
289113
289374
  const pkg = req2(pkgPath);
289114
289375
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
289115
289376
  currentVersion = pkg.version ?? "0.0.0";
@@ -290164,10 +290425,10 @@ var init_commands = __esm({
290164
290425
  });
290165
290426
 
290166
290427
  // packages/cli/dist/tui/project-context.js
290167
- import { existsSync as existsSync49, readFileSync as readFileSync37, readdirSync as readdirSync15 } from "node:fs";
290168
- import { join as join65, basename as basename13 } from "node:path";
290428
+ import { existsSync as existsSync50, readFileSync as readFileSync38, readdirSync as readdirSync15 } from "node:fs";
290429
+ import { join as join66, basename as basename13 } from "node:path";
290169
290430
  import { execSync as execSync34 } from "node:child_process";
290170
- import { homedir as homedir20, platform as platform4, release } from "node:os";
290431
+ import { homedir as homedir21, platform as platform4, release } from "node:os";
290171
290432
  function getModelTier(modelName) {
290172
290433
  const m2 = modelName.toLowerCase();
290173
290434
  const sizeMatch = m2.match(/\b(\d+)b\b/);
@@ -290200,10 +290461,10 @@ function loadProjectMap(repoRoot) {
290200
290461
  if (!hasOaDirectory(repoRoot)) {
290201
290462
  initOaDirectory(repoRoot);
290202
290463
  }
290203
- const mapPath2 = join65(repoRoot, OA_DIR, "context", "project-map.md");
290204
- if (existsSync49(mapPath2)) {
290464
+ const mapPath2 = join66(repoRoot, OA_DIR, "context", "project-map.md");
290465
+ if (existsSync50(mapPath2)) {
290205
290466
  try {
290206
- const content = readFileSync37(mapPath2, "utf-8");
290467
+ const content = readFileSync38(mapPath2, "utf-8");
290207
290468
  return content;
290208
290469
  } catch {
290209
290470
  }
@@ -290244,31 +290505,31 @@ ${log22}`);
290244
290505
  }
290245
290506
  function loadMemoryContext(repoRoot) {
290246
290507
  const sections = [];
290247
- const oaMemDir = join65(repoRoot, OA_DIR, "memory");
290508
+ const oaMemDir = join66(repoRoot, OA_DIR, "memory");
290248
290509
  const oaEntries = loadMemoryDir(oaMemDir, "project");
290249
290510
  if (oaEntries)
290250
290511
  sections.push(oaEntries);
290251
- const legacyMemDir = join65(repoRoot, ".open-agents", "memory");
290252
- if (legacyMemDir !== oaMemDir && existsSync49(legacyMemDir)) {
290512
+ const legacyMemDir = join66(repoRoot, ".open-agents", "memory");
290513
+ if (legacyMemDir !== oaMemDir && existsSync50(legacyMemDir)) {
290253
290514
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
290254
290515
  if (legacyEntries)
290255
290516
  sections.push(legacyEntries);
290256
290517
  }
290257
- const globalMemDir = join65(homedir20(), ".open-agents", "memory");
290518
+ const globalMemDir = join66(homedir21(), ".open-agents", "memory");
290258
290519
  const globalEntries = loadMemoryDir(globalMemDir, "global");
290259
290520
  if (globalEntries)
290260
290521
  sections.push(globalEntries);
290261
290522
  return sections.join("\n\n");
290262
290523
  }
290263
290524
  function loadMemoryDir(memDir, scope) {
290264
- if (!existsSync49(memDir))
290525
+ if (!existsSync50(memDir))
290265
290526
  return "";
290266
290527
  const lines = [];
290267
290528
  try {
290268
290529
  const files = readdirSync15(memDir).filter((f2) => f2.endsWith(".json"));
290269
290530
  for (const file of files.slice(0, 10)) {
290270
290531
  try {
290271
- const raw = readFileSync37(join65(memDir, file), "utf-8");
290532
+ const raw = readFileSync38(join66(memDir, file), "utf-8");
290272
290533
  const entries = JSON.parse(raw);
290273
290534
  const topic = basename13(file, ".json");
290274
290535
  const keys = Object.keys(entries);
@@ -291413,8 +291674,8 @@ __export(banner_exports, {
291413
291674
  saveBannerDesign: () => saveBannerDesign,
291414
291675
  setGridText: () => setGridText
291415
291676
  });
291416
- import { existsSync as existsSync50, readFileSync as readFileSync38, writeFileSync as writeFileSync23, mkdirSync as mkdirSync22 } from "node:fs";
291417
- import { join as join66 } from "node:path";
291677
+ import { existsSync as existsSync51, readFileSync as readFileSync39, writeFileSync as writeFileSync24, mkdirSync as mkdirSync23 } from "node:fs";
291678
+ import { join as join67 } from "node:path";
291418
291679
  function generateMnemonic(seed) {
291419
291680
  let h = 2166136261;
291420
291681
  for (let i2 = 0; i2 < seed.length; i2++) {
@@ -291609,23 +291870,23 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
291609
291870
  };
291610
291871
  }
291611
291872
  function saveBannerDesign(workDir, design) {
291612
- const dir = join66(workDir, ".oa", "banners");
291613
- mkdirSync22(dir, { recursive: true });
291614
- writeFileSync23(join66(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
291873
+ const dir = join67(workDir, ".oa", "banners");
291874
+ mkdirSync23(dir, { recursive: true });
291875
+ writeFileSync24(join67(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
291615
291876
  }
291616
291877
  function loadBannerDesign(workDir, id) {
291617
- const file = join66(workDir, ".oa", "banners", `${id}.json`);
291618
- if (!existsSync50(file))
291878
+ const file = join67(workDir, ".oa", "banners", `${id}.json`);
291879
+ if (!existsSync51(file))
291619
291880
  return null;
291620
291881
  try {
291621
- return JSON.parse(readFileSync38(file, "utf8"));
291882
+ return JSON.parse(readFileSync39(file, "utf8"));
291622
291883
  } catch {
291623
291884
  return null;
291624
291885
  }
291625
291886
  }
291626
291887
  function listBannerDesigns(workDir) {
291627
- const dir = join66(workDir, ".oa", "banners");
291628
- if (!existsSync50(dir))
291888
+ const dir = join67(workDir, ".oa", "banners");
291889
+ if (!existsSync51(dir))
291629
291890
  return [];
291630
291891
  try {
291631
291892
  const { readdirSync: readdirSync26 } = __require("node:fs");
@@ -291993,22 +292254,22 @@ var init_banner = __esm({
291993
292254
  });
291994
292255
 
291995
292256
  // packages/cli/dist/tui/carousel-descriptors.js
291996
- import { existsSync as existsSync51, readFileSync as readFileSync39, writeFileSync as writeFileSync24, mkdirSync as mkdirSync23, readdirSync as readdirSync16 } from "node:fs";
291997
- import { join as join67, basename as basename14 } from "node:path";
292257
+ import { existsSync as existsSync52, readFileSync as readFileSync40, writeFileSync as writeFileSync25, mkdirSync as mkdirSync24, readdirSync as readdirSync16 } from "node:fs";
292258
+ import { join as join68, basename as basename14 } from "node:path";
291998
292259
  function loadToolProfile(repoRoot) {
291999
- const filePath = join67(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
292260
+ const filePath = join68(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
292000
292261
  try {
292001
- if (!existsSync51(filePath))
292262
+ if (!existsSync52(filePath))
292002
292263
  return null;
292003
- return JSON.parse(readFileSync39(filePath, "utf-8"));
292264
+ return JSON.parse(readFileSync40(filePath, "utf-8"));
292004
292265
  } catch {
292005
292266
  return null;
292006
292267
  }
292007
292268
  }
292008
292269
  function saveToolProfile(repoRoot, profile) {
292009
- const contextDir = join67(repoRoot, OA_DIR, "context");
292010
- mkdirSync23(contextDir, { recursive: true });
292011
- writeFileSync24(join67(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
292270
+ const contextDir = join68(repoRoot, OA_DIR, "context");
292271
+ mkdirSync24(contextDir, { recursive: true });
292272
+ writeFileSync25(join68(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
292012
292273
  }
292013
292274
  function categorizeToolCall(toolName) {
292014
292275
  for (const cat2 of TOOL_CATEGORIES) {
@@ -292066,25 +292327,25 @@ function weightedColor(profile) {
292066
292327
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
292067
292328
  }
292068
292329
  function loadCachedDescriptors(repoRoot) {
292069
- const filePath = join67(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
292330
+ const filePath = join68(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
292070
292331
  try {
292071
- if (!existsSync51(filePath))
292332
+ if (!existsSync52(filePath))
292072
292333
  return null;
292073
- const cached = JSON.parse(readFileSync39(filePath, "utf-8"));
292334
+ const cached = JSON.parse(readFileSync40(filePath, "utf-8"));
292074
292335
  return cached.phrases.length > 0 ? cached.phrases : null;
292075
292336
  } catch {
292076
292337
  return null;
292077
292338
  }
292078
292339
  }
292079
292340
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
292080
- const contextDir = join67(repoRoot, OA_DIR, "context");
292081
- mkdirSync23(contextDir, { recursive: true });
292341
+ const contextDir = join68(repoRoot, OA_DIR, "context");
292342
+ mkdirSync24(contextDir, { recursive: true });
292082
292343
  const cached = {
292083
292344
  phrases,
292084
292345
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
292085
292346
  sourceHash
292086
292347
  };
292087
- writeFileSync24(join67(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
292348
+ writeFileSync25(join68(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
292088
292349
  }
292089
292350
  function generateDescriptors(repoRoot) {
292090
292351
  const profile = loadToolProfile(repoRoot);
@@ -292132,11 +292393,11 @@ function generateDescriptors(repoRoot) {
292132
292393
  return phrases;
292133
292394
  }
292134
292395
  function extractFromPackageJson(repoRoot, tags) {
292135
- const pkgPath = join67(repoRoot, "package.json");
292396
+ const pkgPath = join68(repoRoot, "package.json");
292136
292397
  try {
292137
- if (!existsSync51(pkgPath))
292398
+ if (!existsSync52(pkgPath))
292138
292399
  return;
292139
- const pkg = JSON.parse(readFileSync39(pkgPath, "utf-8"));
292400
+ const pkg = JSON.parse(readFileSync40(pkgPath, "utf-8"));
292140
292401
  if (pkg.name && typeof pkg.name === "string") {
292141
292402
  const parts = pkg.name.replace(/^@/, "").split("/");
292142
292403
  for (const p2 of parts)
@@ -292180,7 +292441,7 @@ function extractFromManifests(repoRoot, tags) {
292180
292441
  { file: ".github/workflows", tag: "ci/cd" }
292181
292442
  ];
292182
292443
  for (const check of manifestChecks) {
292183
- if (existsSync51(join67(repoRoot, check.file))) {
292444
+ if (existsSync52(join68(repoRoot, check.file))) {
292184
292445
  tags.push(check.tag);
292185
292446
  }
292186
292447
  }
@@ -292202,16 +292463,16 @@ function extractFromSessions(repoRoot, tags) {
292202
292463
  }
292203
292464
  }
292204
292465
  function extractFromMemory(repoRoot, tags) {
292205
- const memoryDir = join67(repoRoot, OA_DIR, "memory");
292466
+ const memoryDir = join68(repoRoot, OA_DIR, "memory");
292206
292467
  try {
292207
- if (!existsSync51(memoryDir))
292468
+ if (!existsSync52(memoryDir))
292208
292469
  return;
292209
292470
  const files = readdirSync16(memoryDir).filter((f2) => f2.endsWith(".json"));
292210
292471
  for (const file of files) {
292211
292472
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
292212
292473
  tags.push(topic);
292213
292474
  try {
292214
- const data = JSON.parse(readFileSync39(join67(memoryDir, file), "utf-8"));
292475
+ const data = JSON.parse(readFileSync40(join68(memoryDir, file), "utf-8"));
292215
292476
  if (data && typeof data === "object") {
292216
292477
  const keys = Object.keys(data).slice(0, 3);
292217
292478
  for (const key of keys) {
@@ -292882,13 +293143,13 @@ var init_stream_renderer = __esm({
292882
293143
  });
292883
293144
 
292884
293145
  // packages/cli/dist/tui/edit-history.js
292885
- import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync24 } from "node:fs";
292886
- import { join as join68 } from "node:path";
293146
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync25 } from "node:fs";
293147
+ import { join as join69 } from "node:path";
292887
293148
  function createEditHistoryLogger(repoRoot, sessionId) {
292888
- const historyDir = join68(repoRoot, ".oa", "history");
292889
- const logPath2 = join68(historyDir, "edits.jsonl");
293149
+ const historyDir = join69(repoRoot, ".oa", "history");
293150
+ const logPath2 = join69(historyDir, "edits.jsonl");
292890
293151
  try {
292891
- mkdirSync24(historyDir, { recursive: true });
293152
+ mkdirSync25(historyDir, { recursive: true });
292892
293153
  } catch {
292893
293154
  }
292894
293155
  function logToolCall(toolName, toolArgs, success) {
@@ -292997,17 +293258,17 @@ var init_edit_history = __esm({
292997
293258
  });
292998
293259
 
292999
293260
  // packages/cli/dist/tui/promptLoader.js
293000
- import { readFileSync as readFileSync40, existsSync as existsSync52 } from "node:fs";
293001
- import { join as join69, dirname as dirname21 } from "node:path";
293002
- import { fileURLToPath as fileURLToPath13 } from "node:url";
293261
+ import { readFileSync as readFileSync41, existsSync as existsSync53 } from "node:fs";
293262
+ import { join as join70, dirname as dirname22 } from "node:path";
293263
+ import { fileURLToPath as fileURLToPath14 } from "node:url";
293003
293264
  function loadPrompt3(promptPath, vars) {
293004
293265
  let content = cache6.get(promptPath);
293005
293266
  if (content === void 0) {
293006
- const fullPath = join69(PROMPTS_DIR3, promptPath);
293007
- if (!existsSync52(fullPath)) {
293267
+ const fullPath = join70(PROMPTS_DIR3, promptPath);
293268
+ if (!existsSync53(fullPath)) {
293008
293269
  throw new Error(`Prompt file not found: ${fullPath}`);
293009
293270
  }
293010
- content = readFileSync40(fullPath, "utf-8");
293271
+ content = readFileSync41(fullPath, "utf-8");
293011
293272
  cache6.set(promptPath, content);
293012
293273
  }
293013
293274
  if (!vars)
@@ -293018,25 +293279,25 @@ var __filename5, __dirname7, devPath2, publishedPath2, PROMPTS_DIR3, cache6;
293018
293279
  var init_promptLoader3 = __esm({
293019
293280
  "packages/cli/dist/tui/promptLoader.js"() {
293020
293281
  "use strict";
293021
- __filename5 = fileURLToPath13(import.meta.url);
293022
- __dirname7 = dirname21(__filename5);
293023
- devPath2 = join69(__dirname7, "..", "..", "prompts");
293024
- publishedPath2 = join69(__dirname7, "..", "prompts");
293025
- PROMPTS_DIR3 = existsSync52(devPath2) ? devPath2 : publishedPath2;
293282
+ __filename5 = fileURLToPath14(import.meta.url);
293283
+ __dirname7 = dirname22(__filename5);
293284
+ devPath2 = join70(__dirname7, "..", "..", "prompts");
293285
+ publishedPath2 = join70(__dirname7, "..", "prompts");
293286
+ PROMPTS_DIR3 = existsSync53(devPath2) ? devPath2 : publishedPath2;
293026
293287
  cache6 = /* @__PURE__ */ new Map();
293027
293288
  }
293028
293289
  });
293029
293290
 
293030
293291
  // packages/cli/dist/tui/dream-engine.js
293031
- import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync25, readFileSync as readFileSync41, existsSync as existsSync53, cpSync, rmSync as rmSync3, readdirSync as readdirSync17 } from "node:fs";
293032
- import { join as join70, basename as basename15 } from "node:path";
293292
+ import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync26, readFileSync as readFileSync42, existsSync as existsSync54, cpSync, rmSync as rmSync3, readdirSync as readdirSync17 } from "node:fs";
293293
+ import { join as join71, basename as basename15 } from "node:path";
293033
293294
  import { execSync as execSync35 } from "node:child_process";
293034
293295
  function loadAutoresearchMemory(repoRoot) {
293035
- const memoryPath = join70(repoRoot, ".oa", "memory", "autoresearch.json");
293036
- if (!existsSync53(memoryPath))
293296
+ const memoryPath = join71(repoRoot, ".oa", "memory", "autoresearch.json");
293297
+ if (!existsSync54(memoryPath))
293037
293298
  return "";
293038
293299
  try {
293039
- const raw = readFileSync41(memoryPath, "utf-8");
293300
+ const raw = readFileSync42(memoryPath, "utf-8");
293040
293301
  const data = JSON.parse(raw);
293041
293302
  const sections = [];
293042
293303
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -293226,14 +293487,14 @@ var init_dream_engine = __esm({
293226
293487
  const content = String(args["content"] ?? "");
293227
293488
  if (!rawPath)
293228
293489
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
293229
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join70(this.autoresearchDir, basename15(rawPath)) : join70(this.autoresearchDir, rawPath);
293490
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join71(this.autoresearchDir, basename15(rawPath)) : join71(this.autoresearchDir, rawPath);
293230
293491
  if (!targetPath.startsWith(this.autoresearchDir)) {
293231
293492
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
293232
293493
  }
293233
293494
  try {
293234
- const dir = join70(targetPath, "..");
293235
- mkdirSync25(dir, { recursive: true });
293236
- writeFileSync25(targetPath, content, "utf-8");
293495
+ const dir = join71(targetPath, "..");
293496
+ mkdirSync26(dir, { recursive: true });
293497
+ writeFileSync26(targetPath, content, "utf-8");
293237
293498
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
293238
293499
  } catch (err) {
293239
293500
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -293261,20 +293522,20 @@ var init_dream_engine = __esm({
293261
293522
  const rawPath = String(args["path"] ?? "");
293262
293523
  const oldStr = String(args["old_string"] ?? "");
293263
293524
  const newStr = String(args["new_string"] ?? "");
293264
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join70(this.autoresearchDir, basename15(rawPath)) : join70(this.autoresearchDir, rawPath);
293525
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join71(this.autoresearchDir, basename15(rawPath)) : join71(this.autoresearchDir, rawPath);
293265
293526
  if (!targetPath.startsWith(this.autoresearchDir)) {
293266
293527
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
293267
293528
  }
293268
293529
  try {
293269
- if (!existsSync53(targetPath)) {
293530
+ if (!existsSync54(targetPath)) {
293270
293531
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
293271
293532
  }
293272
- let content = readFileSync41(targetPath, "utf-8");
293533
+ let content = readFileSync42(targetPath, "utf-8");
293273
293534
  if (!content.includes(oldStr)) {
293274
293535
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
293275
293536
  }
293276
293537
  content = content.replace(oldStr, newStr);
293277
- writeFileSync25(targetPath, content, "utf-8");
293538
+ writeFileSync26(targetPath, content, "utf-8");
293278
293539
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
293279
293540
  } catch (err) {
293280
293541
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -293315,14 +293576,14 @@ var init_dream_engine = __esm({
293315
293576
  const content = String(args["content"] ?? "");
293316
293577
  if (!rawPath)
293317
293578
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
293318
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join70(this.dreamsDir, basename15(rawPath)) : join70(this.dreamsDir, rawPath);
293579
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join71(this.dreamsDir, basename15(rawPath)) : join71(this.dreamsDir, rawPath);
293319
293580
  if (!targetPath.startsWith(this.dreamsDir)) {
293320
293581
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start2 };
293321
293582
  }
293322
293583
  try {
293323
- const dir = join70(targetPath, "..");
293324
- mkdirSync25(dir, { recursive: true });
293325
- writeFileSync25(targetPath, content, "utf-8");
293584
+ const dir = join71(targetPath, "..");
293585
+ mkdirSync26(dir, { recursive: true });
293586
+ writeFileSync26(targetPath, content, "utf-8");
293326
293587
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
293327
293588
  } catch (err) {
293328
293589
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -293350,20 +293611,20 @@ var init_dream_engine = __esm({
293350
293611
  const rawPath = String(args["path"] ?? "");
293351
293612
  const oldStr = String(args["old_string"] ?? "");
293352
293613
  const newStr = String(args["new_string"] ?? "");
293353
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join70(this.dreamsDir, basename15(rawPath)) : join70(this.dreamsDir, rawPath);
293614
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join71(this.dreamsDir, basename15(rawPath)) : join71(this.dreamsDir, rawPath);
293354
293615
  if (!targetPath.startsWith(this.dreamsDir)) {
293355
293616
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start2 };
293356
293617
  }
293357
293618
  try {
293358
- if (!existsSync53(targetPath)) {
293619
+ if (!existsSync54(targetPath)) {
293359
293620
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
293360
293621
  }
293361
- let content = readFileSync41(targetPath, "utf-8");
293622
+ let content = readFileSync42(targetPath, "utf-8");
293362
293623
  if (!content.includes(oldStr)) {
293363
293624
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
293364
293625
  }
293365
293626
  content = content.replace(oldStr, newStr);
293366
- writeFileSync25(targetPath, content, "utf-8");
293627
+ writeFileSync26(targetPath, content, "utf-8");
293367
293628
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
293368
293629
  } catch (err) {
293369
293630
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -293417,7 +293678,7 @@ var init_dream_engine = __esm({
293417
293678
  constructor(config, repoRoot) {
293418
293679
  this.config = config;
293419
293680
  this.repoRoot = repoRoot;
293420
- this.dreamsDir = join70(repoRoot, ".oa", "dreams");
293681
+ this.dreamsDir = join71(repoRoot, ".oa", "dreams");
293421
293682
  this.state = {
293422
293683
  mode: "default",
293423
293684
  active: false,
@@ -293438,6 +293699,9 @@ var init_dream_engine = __esm({
293438
293699
  if (this.state.active) {
293439
293700
  throw new Error("Already dreaming. Use /dream stop first.");
293440
293701
  }
293702
+ if (mode === "consolidate") {
293703
+ return this.runConsolidation(onEvent);
293704
+ }
293441
293705
  this.abortController = new AbortController();
293442
293706
  const totalCycles = mode === "deep" ? 3 : mode === "lucid" ? 2 : 1;
293443
293707
  this.state = {
@@ -293448,7 +293712,7 @@ var init_dream_engine = __esm({
293448
293712
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
293449
293713
  results: []
293450
293714
  };
293451
- mkdirSync25(this.dreamsDir, { recursive: true });
293715
+ mkdirSync26(this.dreamsDir, { recursive: true });
293452
293716
  this.saveDreamState();
293453
293717
  try {
293454
293718
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -293501,8 +293765,8 @@ ${result.summary}`;
293501
293765
  if (mode !== "default" || cycle === totalCycles) {
293502
293766
  renderDreamContraction(cycle);
293503
293767
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
293504
- const summaryPath = join70(this.dreamsDir, `cycle-${cycle}-summary.md`);
293505
- writeFileSync25(summaryPath, cycleSummary, "utf-8");
293768
+ const summaryPath = join71(this.dreamsDir, `cycle-${cycle}-summary.md`);
293769
+ writeFileSync26(summaryPath, cycleSummary, "utf-8");
293506
293770
  }
293507
293771
  if (mode === "lucid" && !this.abortController.signal.aborted) {
293508
293772
  this.saveVersionCheckpoint(cycle);
@@ -293714,7 +293978,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
293714
293978
  }
293715
293979
  /** Build role-specific tool sets for swarm agents */
293716
293980
  buildSwarmTools(role, _workspace) {
293717
- const autoresearchDir = join70(this.repoRoot, ".oa", "autoresearch");
293981
+ const autoresearchDir = join71(this.repoRoot, ".oa", "autoresearch");
293718
293982
  const taskComplete = this.createSwarmTaskCompleteTool(role);
293719
293983
  switch (role) {
293720
293984
  case "researcher": {
@@ -294078,7 +294342,7 @@ INSTRUCTIONS:
294078
294342
  2. Summarize the key learnings and next steps
294079
294343
 
294080
294344
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
294081
- const reportPath = join70(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
294345
+ const reportPath = join71(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
294082
294346
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
294083
294347
 
294084
294348
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -294100,8 +294364,8 @@ ${summaryResult}
294100
294364
  *Generated by open-agents autoresearch swarm*
294101
294365
  `;
294102
294366
  try {
294103
- mkdirSync25(this.dreamsDir, { recursive: true });
294104
- writeFileSync25(reportPath, report, "utf-8");
294367
+ mkdirSync26(this.dreamsDir, { recursive: true });
294368
+ writeFileSync26(reportPath, report, "utf-8");
294105
294369
  } catch {
294106
294370
  }
294107
294371
  renderSwarmComplete(workspace);
@@ -294167,9 +294431,9 @@ ${summaryResult}
294167
294431
  }
294168
294432
  /** Save workspace backup for lucid mode */
294169
294433
  saveVersionCheckpoint(cycle) {
294170
- const checkpointDir = join70(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
294434
+ const checkpointDir = join71(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
294171
294435
  try {
294172
- mkdirSync25(checkpointDir, { recursive: true });
294436
+ mkdirSync26(checkpointDir, { recursive: true });
294173
294437
  try {
294174
294438
  const gitStatus = execSync35("git status --porcelain", {
294175
294439
  cwd: this.repoRoot,
@@ -294186,10 +294450,10 @@ ${summaryResult}
294186
294450
  encoding: "utf-8",
294187
294451
  timeout: 5e3
294188
294452
  }).trim();
294189
- writeFileSync25(join70(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
294190
- writeFileSync25(join70(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
294191
- writeFileSync25(join70(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
294192
- writeFileSync25(join70(checkpointDir, "checkpoint.json"), JSON.stringify({
294453
+ writeFileSync26(join71(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
294454
+ writeFileSync26(join71(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
294455
+ writeFileSync26(join71(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
294456
+ writeFileSync26(join71(checkpointDir, "checkpoint.json"), JSON.stringify({
294193
294457
  cycle,
294194
294458
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
294195
294459
  gitHash,
@@ -294197,7 +294461,7 @@ ${summaryResult}
294197
294461
  }, null, 2), "utf-8");
294198
294462
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
294199
294463
  } catch {
294200
- writeFileSync25(join70(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
294464
+ writeFileSync26(join71(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
294201
294465
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
294202
294466
  }
294203
294467
  } catch (err) {
@@ -294255,14 +294519,107 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
294255
294519
  ---
294256
294520
  *Auto-generated by open-agents dream engine*
294257
294521
  `;
294258
- writeFileSync25(join70(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
294522
+ writeFileSync26(join71(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
294523
+ } catch {
294524
+ }
294525
+ }
294526
+ /**
294527
+ * WO-LL-01: Memory Consolidation — runs the consolidation prompt through
294528
+ * AgenticRunner with read/write tools targeting .oa/memory/.
294529
+ *
294530
+ * 4-phase: Orient → Gather → Consolidate → Prune
294531
+ * Hannover reference: services/autoDream/autoDream.ts
294532
+ */
294533
+ async runConsolidation(onEvent) {
294534
+ this.state = {
294535
+ mode: "consolidate",
294536
+ active: true,
294537
+ cycleCount: 1,
294538
+ currentCycle: 1,
294539
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
294540
+ results: []
294541
+ };
294542
+ renderInfo("Memory consolidation starting \u2014 Phase 1: Orient \u2192 Phase 2: Gather \u2192 Phase 3: Consolidate \u2192 Phase 4: Prune");
294543
+ const memoryDir = join71(this.repoRoot, ".oa", "memory");
294544
+ mkdirSync26(memoryDir, { recursive: true });
294545
+ let prompt;
294546
+ try {
294547
+ prompt = loadPrompt3("tui/dream-consolidate.md", {
294548
+ memoryDir,
294549
+ lookbackEntries: "10"
294550
+ });
294259
294551
  } catch {
294552
+ prompt = `Consolidate the memory files in ${memoryDir}. List the directory, read files, merge duplicates, delete stale entries, update the index.`;
294553
+ }
294554
+ const backend = new OllamaAgenticBackend(this.config.backendUrl, this.config.model, this.config.apiKey);
294555
+ const modelTier = getModelTier(this.config.model);
294556
+ const runner = new AgenticRunner(backend, {
294557
+ maxTurns: 20,
294558
+ maxTokens: 4096,
294559
+ temperature: 0,
294560
+ requestTimeoutMs: this.config.timeoutMs,
294561
+ taskTimeoutMs: this.config.timeoutMs * 3,
294562
+ compactionThreshold: 24e3,
294563
+ contextWindowSize: 32768,
294564
+ modelTier
294565
+ });
294566
+ const tools = [
294567
+ new FileReadTool(this.repoRoot),
294568
+ new FileWriteTool(this.repoRoot),
294569
+ new FileEditTool(this.repoRoot),
294570
+ new ListDirectoryTool(this.repoRoot),
294571
+ new GrepSearchTool(this.repoRoot),
294572
+ new GlobFindTool(this.repoRoot),
294573
+ new ShellTool(this.repoRoot),
294574
+ new MemoryReadTool(this.repoRoot),
294575
+ new MemoryWriteTool(this.repoRoot),
294576
+ new MemorySearchTool(this.repoRoot)
294577
+ ].map((t2) => ({
294578
+ name: t2.name,
294579
+ description: t2.description,
294580
+ parameters: t2.parameters,
294581
+ execute: t2.execute.bind(t2)
294582
+ }));
294583
+ tools.push({
294584
+ name: "task_complete",
294585
+ description: "Signal consolidation is done. Args: {summary: string}",
294586
+ parameters: { type: "object", properties: { summary: { type: "string" } }, required: ["summary"] },
294587
+ execute: async (args) => ({ success: true, output: String(args["summary"] ?? "done") })
294588
+ });
294589
+ for (const t2 of tools)
294590
+ runner.registerTool(t2);
294591
+ if (onEvent)
294592
+ runner.onEvent(onEvent);
294593
+ const startMs = Date.now();
294594
+ try {
294595
+ const result = await runner.run(prompt);
294596
+ const durationMs = Date.now() - startMs;
294597
+ this.state.results.push({
294598
+ cycle: 1,
294599
+ stage: "consolidation",
294600
+ ideas: [],
294601
+ proposals: [],
294602
+ filesGenerated: [],
294603
+ durationMs
294604
+ });
294605
+ try {
294606
+ writeFileSync26(join71(memoryDir, ".last-consolidation"), JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), summary: result.summary?.slice(0, 500) }) + "\n");
294607
+ } catch {
294608
+ }
294609
+ renderInfo(`Consolidation complete: ${result.turns} turns, ${result.toolCalls} tool calls, ${(durationMs / 1e3).toFixed(1)}s`);
294610
+ if (result.summary)
294611
+ renderInfo(`Summary: ${result.summary.slice(0, 200)}`);
294612
+ } catch (err) {
294613
+ renderWarning(`Consolidation failed: ${err instanceof Error ? err.message : String(err)}`);
294260
294614
  }
294615
+ this.state.active = false;
294616
+ this.saveDreamState();
294617
+ return this.state;
294261
294618
  }
294262
294619
  /** Save dream state for resume/inspection */
294263
294620
  saveDreamState() {
294264
294621
  try {
294265
- writeFileSync25(join70(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
294622
+ writeFileSync26(join71(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
294266
294623
  } catch {
294267
294624
  }
294268
294625
  }
@@ -294636,8 +294993,8 @@ var init_bless_engine = __esm({
294636
294993
  });
294637
294994
 
294638
294995
  // packages/cli/dist/tui/dmn-engine.js
294639
- import { existsSync as existsSync54, readFileSync as readFileSync42, writeFileSync as writeFileSync26, mkdirSync as mkdirSync26, readdirSync as readdirSync18, unlinkSync as unlinkSync10 } from "node:fs";
294640
- import { join as join71, basename as basename16 } from "node:path";
294996
+ import { existsSync as existsSync55, readFileSync as readFileSync43, writeFileSync as writeFileSync27, mkdirSync as mkdirSync27, readdirSync as readdirSync18, unlinkSync as unlinkSync11 } from "node:fs";
294997
+ import { join as join72, basename as basename16 } from "node:path";
294641
294998
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
294642
294999
  const competenceReport = competence.length > 0 ? competence.map((c4) => {
294643
295000
  const rate = c4.attempts > 0 ? Math.round(c4.successes / c4.attempts * 100) : 0;
@@ -294757,9 +295114,9 @@ var init_dmn_engine = __esm({
294757
295114
  constructor(config, repoRoot) {
294758
295115
  this.config = config;
294759
295116
  this.repoRoot = repoRoot;
294760
- this.stateDir = join71(repoRoot, ".oa", "dmn");
294761
- this.historyDir = join71(repoRoot, ".oa", "dmn", "cycles");
294762
- mkdirSync26(this.historyDir, { recursive: true });
295117
+ this.stateDir = join72(repoRoot, ".oa", "dmn");
295118
+ this.historyDir = join72(repoRoot, ".oa", "dmn", "cycles");
295119
+ mkdirSync27(this.historyDir, { recursive: true });
294763
295120
  this.loadState();
294764
295121
  }
294765
295122
  get stats() {
@@ -295348,11 +295705,11 @@ OUTPUT: Call task_complete with JSON:
295348
295705
  async gatherMemoryTopics() {
295349
295706
  const topics = [];
295350
295707
  const dirs = [
295351
- join71(this.repoRoot, ".oa", "memory"),
295352
- join71(this.repoRoot, ".open-agents", "memory")
295708
+ join72(this.repoRoot, ".oa", "memory"),
295709
+ join72(this.repoRoot, ".open-agents", "memory")
295353
295710
  ];
295354
295711
  for (const dir of dirs) {
295355
- if (!existsSync54(dir))
295712
+ if (!existsSync55(dir))
295356
295713
  continue;
295357
295714
  try {
295358
295715
  const files = readdirSync18(dir).filter((f2) => f2.endsWith(".json"));
@@ -295368,29 +295725,29 @@ OUTPUT: Call task_complete with JSON:
295368
295725
  }
295369
295726
  // ── State persistence ─────────────────────────────────────────────────
295370
295727
  loadState() {
295371
- const path5 = join71(this.stateDir, "state.json");
295372
- if (existsSync54(path5)) {
295728
+ const path5 = join72(this.stateDir, "state.json");
295729
+ if (existsSync55(path5)) {
295373
295730
  try {
295374
- this.state = JSON.parse(readFileSync42(path5, "utf-8"));
295731
+ this.state = JSON.parse(readFileSync43(path5, "utf-8"));
295375
295732
  } catch {
295376
295733
  }
295377
295734
  }
295378
295735
  }
295379
295736
  saveState() {
295380
295737
  try {
295381
- writeFileSync26(join71(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
295738
+ writeFileSync27(join72(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
295382
295739
  } catch {
295383
295740
  }
295384
295741
  }
295385
295742
  saveCycleResult(result) {
295386
295743
  try {
295387
295744
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
295388
- writeFileSync26(join71(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
295745
+ writeFileSync27(join72(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
295389
295746
  const files = readdirSync18(this.historyDir).filter((f2) => f2.startsWith("cycle-") && f2.endsWith(".json")).sort();
295390
295747
  if (files.length > 50) {
295391
295748
  for (const old of files.slice(0, files.length - 50)) {
295392
295749
  try {
295393
- unlinkSync10(join71(this.historyDir, old));
295750
+ unlinkSync11(join72(this.historyDir, old));
295394
295751
  } catch {
295395
295752
  }
295396
295753
  }
@@ -295403,8 +295760,8 @@ OUTPUT: Call task_complete with JSON:
295403
295760
  });
295404
295761
 
295405
295762
  // packages/cli/dist/tui/snr-engine.js
295406
- import { existsSync as existsSync55, readdirSync as readdirSync19, readFileSync as readFileSync43 } from "node:fs";
295407
- import { join as join72, basename as basename17 } from "node:path";
295763
+ import { existsSync as existsSync56, readdirSync as readdirSync19, readFileSync as readFileSync44 } from "node:fs";
295764
+ import { join as join73, basename as basename17 } from "node:path";
295408
295765
  function computeDPrime(signalScores, noiseScores) {
295409
295766
  if (signalScores.length === 0 || noiseScores.length === 0)
295410
295767
  return 0;
@@ -295644,11 +296001,11 @@ Call task_complete with the JSON array when done.`, onEvent)
295644
296001
  loadMemoryEntries(topics) {
295645
296002
  const entries = [];
295646
296003
  const dirs = [
295647
- join72(this.repoRoot, ".oa", "memory"),
295648
- join72(this.repoRoot, ".open-agents", "memory")
296004
+ join73(this.repoRoot, ".oa", "memory"),
296005
+ join73(this.repoRoot, ".open-agents", "memory")
295649
296006
  ];
295650
296007
  for (const dir of dirs) {
295651
- if (!existsSync55(dir))
296008
+ if (!existsSync56(dir))
295652
296009
  continue;
295653
296010
  try {
295654
296011
  const files = readdirSync19(dir).filter((f2) => f2.endsWith(".json"));
@@ -295657,7 +296014,7 @@ Call task_complete with the JSON array when done.`, onEvent)
295657
296014
  if (topics.length > 0 && !topics.includes(topic))
295658
296015
  continue;
295659
296016
  try {
295660
- const data = JSON.parse(readFileSync43(join72(dir, f2), "utf-8"));
296017
+ const data = JSON.parse(readFileSync44(join73(dir, f2), "utf-8"));
295661
296018
  for (const [key, val] of Object.entries(data)) {
295662
296019
  const value2 = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
295663
296020
  entries.push({ topic, key, value: value2 });
@@ -296224,8 +296581,8 @@ var init_tool_policy = __esm({
296224
296581
  });
296225
296582
 
296226
296583
  // packages/cli/dist/tui/telegram-bridge.js
296227
- import { mkdirSync as mkdirSync27, existsSync as existsSync56, unlinkSync as unlinkSync11, readdirSync as readdirSync20, statSync as statSync16 } from "node:fs";
296228
- import { join as join73, resolve as resolve32 } from "node:path";
296584
+ import { mkdirSync as mkdirSync28, existsSync as existsSync57, unlinkSync as unlinkSync12, readdirSync as readdirSync20, statSync as statSync16 } from "node:fs";
296585
+ import { join as join74, resolve as resolve32 } from "node:path";
296229
296586
  import { writeFile as writeFileAsync } from "node:fs/promises";
296230
296587
  function convertMarkdownToTelegramHTML(md) {
296231
296588
  let html = md;
@@ -296553,7 +296910,7 @@ with summary "no_reply" to silently skip without responding.
296553
296910
  this.polling = true;
296554
296911
  this.abortController = new AbortController();
296555
296912
  try {
296556
- mkdirSync27(this.mediaCacheDir, { recursive: true });
296913
+ mkdirSync28(this.mediaCacheDir, { recursive: true });
296557
296914
  } catch {
296558
296915
  }
296559
296916
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -296990,7 +297347,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
296990
297347
  return null;
296991
297348
  const buffer2 = Buffer.from(await res.arrayBuffer());
296992
297349
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension2}`;
296993
- const localPath = join73(this.mediaCacheDir, fileName);
297350
+ const localPath = join74(this.mediaCacheDir, fileName);
296994
297351
  await writeFileAsync(localPath, buffer2);
296995
297352
  return localPath;
296996
297353
  } catch {
@@ -297078,7 +297435,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
297078
297435
  for (const [key, entry] of this.mediaCache) {
297079
297436
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
297080
297437
  try {
297081
- unlinkSync11(entry.localPath);
297438
+ unlinkSync12(entry.localPath);
297082
297439
  } catch {
297083
297440
  }
297084
297441
  this.mediaCache.delete(key);
@@ -298346,7 +298703,7 @@ var init_text_selection = __esm({
298346
298703
  });
298347
298704
 
298348
298705
  // packages/cli/dist/tui/status-bar.js
298349
- import { readFileSync as readFileSync44 } from "node:fs";
298706
+ import { readFileSync as readFileSync45 } from "node:fs";
298350
298707
  function setTerminalTitle(task, version4) {
298351
298708
  if (!process.stdout.isTTY)
298352
298709
  return;
@@ -299085,7 +299442,7 @@ var init_status_bar = __esm({
299085
299442
  if (nexusDir) {
299086
299443
  try {
299087
299444
  const metricsPath = nexusDir + "/remote-metrics.json";
299088
- const raw = readFileSync44(metricsPath, "utf8");
299445
+ const raw = readFileSync45(metricsPath, "utf8");
299089
299446
  const cached = JSON.parse(raw);
299090
299447
  if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
299091
299448
  const m2 = cached.data;
@@ -301394,13 +301751,13 @@ var init_direct_input = __esm({
301394
301751
  });
301395
301752
 
301396
301753
  // packages/cli/dist/api/audit-log.js
301397
- import { mkdirSync as mkdirSync28, appendFileSync as appendFileSync5, readFileSync as readFileSync45, existsSync as existsSync57 } from "node:fs";
301398
- import { join as join74 } from "node:path";
301754
+ import { mkdirSync as mkdirSync29, appendFileSync as appendFileSync5, readFileSync as readFileSync46, existsSync as existsSync58 } from "node:fs";
301755
+ import { join as join75 } from "node:path";
301399
301756
  function initAuditLog(oaDir) {
301400
- auditDir = join74(oaDir, "audit");
301401
- auditFile = join74(auditDir, "audit.jsonl");
301757
+ auditDir = join75(oaDir, "audit");
301758
+ auditFile = join75(auditDir, "audit.jsonl");
301402
301759
  try {
301403
- mkdirSync28(auditDir, { recursive: true });
301760
+ mkdirSync29(auditDir, { recursive: true });
301404
301761
  initialized = true;
301405
301762
  } catch {
301406
301763
  }
@@ -301415,10 +301772,10 @@ function recordAudit(record) {
301415
301772
  }
301416
301773
  }
301417
301774
  function queryAudit(opts) {
301418
- if (!initialized || !existsSync57(auditFile))
301775
+ if (!initialized || !existsSync58(auditFile))
301419
301776
  return [];
301420
301777
  try {
301421
- const raw = readFileSync45(auditFile, "utf-8");
301778
+ const raw = readFileSync46(auditFile, "utf-8");
301422
301779
  const lines = raw.split("\n").filter(Boolean);
301423
301780
  let records = lines.map((l2) => {
301424
301781
  try {
@@ -302741,29 +303098,29 @@ var init_auth_oidc = __esm({
302741
303098
 
302742
303099
  // packages/cli/dist/api/chat-session.js
302743
303100
  import { randomUUID as randomUUID4 } from "node:crypto";
302744
- import { existsSync as existsSync58, readFileSync as readFileSync46, readdirSync as readdirSync21 } from "node:fs";
302745
- import { join as join75 } from "node:path";
303101
+ import { existsSync as existsSync59, readFileSync as readFileSync47, readdirSync as readdirSync21 } from "node:fs";
303102
+ import { join as join76 } from "node:path";
302746
303103
  function buildSystemPrompt(cwd4) {
302747
303104
  const parts = [];
302748
303105
  parts.push("You are Open Agent (OA), an AI coding assistant running locally via Ollama. You have access to the user's workspace and can discuss code, files, and projects. Be helpful, concise, and technically precise. When asked about files or code, describe what you know from the conversation context.");
302749
303106
  parts.push(`\\nEnvironment: ${process.platform}, Node ${process.version}, CWD: ${cwd4}`);
302750
- const diaryPath = join75(cwd4, ".oa", "context", "session-diary.md");
302751
- if (existsSync58(diaryPath)) {
303107
+ const diaryPath = join76(cwd4, ".oa", "context", "session-diary.md");
303108
+ if (existsSync59(diaryPath)) {
302752
303109
  try {
302753
- const diary = readFileSync46(diaryPath, "utf-8").slice(0, 1e3);
303110
+ const diary = readFileSync47(diaryPath, "utf-8").slice(0, 1e3);
302754
303111
  parts.push(`\\nPrevious session history:\\n${diary}`);
302755
303112
  } catch {
302756
303113
  }
302757
303114
  }
302758
- const memDir = join75(cwd4, ".oa", "memory");
302759
- if (existsSync58(memDir)) {
303115
+ const memDir = join76(cwd4, ".oa", "memory");
303116
+ if (existsSync59(memDir)) {
302760
303117
  try {
302761
303118
  const files = readdirSync21(memDir).filter((f2) => f2.endsWith(".json")).slice(0, 5);
302762
303119
  if (files.length > 0) {
302763
303120
  parts.push("\\nPersistent memory topics: " + files.map((f2) => f2.replace(".json", "")).join(", "));
302764
303121
  for (const f2 of files.slice(0, 3)) {
302765
303122
  try {
302766
- const data = JSON.parse(readFileSync46(join75(memDir, f2), "utf-8"));
303123
+ const data = JSON.parse(readFileSync47(join76(memDir, f2), "utf-8"));
302767
303124
  const entries = Object.entries(data).slice(0, 3);
302768
303125
  if (entries.length > 0) {
302769
303126
  parts.push(`\\nMemory [${f2.replace(".json", "")}]: ` + entries.map(([k, v]) => `${k}: ${String(v.value ?? v).slice(0, 100)}`).join("; "));
@@ -302776,10 +303133,10 @@ function buildSystemPrompt(cwd4) {
302776
303133
  }
302777
303134
  }
302778
303135
  for (const name10 of ["AGENTS.md", "OA.md", ".open-agents.md"]) {
302779
- const p2 = join75(cwd4, name10);
302780
- if (existsSync58(p2)) {
303136
+ const p2 = join76(cwd4, name10);
303137
+ if (existsSync59(p2)) {
302781
303138
  try {
302782
- const content = readFileSync46(p2, "utf-8").slice(0, 500);
303139
+ const content = readFileSync47(p2, "utf-8").slice(0, 500);
302783
303140
  parts.push(`\\nProject instructions (${name10}):\\n${content}`);
302784
303141
  } catch {
302785
303142
  }
@@ -302857,15 +303214,15 @@ var init_chat_session = __esm({
302857
303214
  });
302858
303215
 
302859
303216
  // packages/cli/dist/api/usage-tracker.js
302860
- import { mkdirSync as mkdirSync29, readFileSync as readFileSync47, writeFileSync as writeFileSync27, existsSync as existsSync59 } from "node:fs";
302861
- import { join as join76 } from "node:path";
303217
+ import { mkdirSync as mkdirSync30, readFileSync as readFileSync48, writeFileSync as writeFileSync28, existsSync as existsSync60 } from "node:fs";
303218
+ import { join as join77 } from "node:path";
302862
303219
  function initUsageTracker(oaDir) {
302863
- const dir = join76(oaDir, "usage");
302864
- mkdirSync29(dir, { recursive: true });
302865
- usageFile = join76(dir, "token-usage.json");
303220
+ const dir = join77(oaDir, "usage");
303221
+ mkdirSync30(dir, { recursive: true });
303222
+ usageFile = join77(dir, "token-usage.json");
302866
303223
  try {
302867
- if (existsSync59(usageFile)) {
302868
- store = JSON.parse(readFileSync47(usageFile, "utf-8"));
303224
+ if (existsSync60(usageFile)) {
303225
+ store = JSON.parse(readFileSync48(usageFile, "utf-8"));
302869
303226
  }
302870
303227
  } catch {
302871
303228
  store = { providers: {}, lastSaved: "" };
@@ -302905,7 +303262,7 @@ function flush2() {
302905
303262
  return;
302906
303263
  try {
302907
303264
  store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
302908
- writeFileSync27(usageFile, JSON.stringify(store, null, 2), "utf-8");
303265
+ writeFileSync28(usageFile, JSON.stringify(store, null, 2), "utf-8");
302909
303266
  dirty = false;
302910
303267
  } catch {
302911
303268
  }
@@ -302933,24 +303290,24 @@ var init_usage_tracker = __esm({
302933
303290
  });
302934
303291
 
302935
303292
  // packages/cli/dist/api/profiles.js
302936
- import { existsSync as existsSync60, readFileSync as readFileSync48, writeFileSync as writeFileSync28, mkdirSync as mkdirSync30, readdirSync as readdirSync22, unlinkSync as unlinkSync12 } from "node:fs";
302937
- import { join as join77 } from "node:path";
302938
- import { homedir as homedir21 } from "node:os";
303293
+ import { existsSync as existsSync61, readFileSync as readFileSync49, writeFileSync as writeFileSync29, mkdirSync as mkdirSync31, readdirSync as readdirSync22, unlinkSync as unlinkSync13 } from "node:fs";
303294
+ import { join as join78 } from "node:path";
303295
+ import { homedir as homedir22 } from "node:os";
302939
303296
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes18, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
302940
303297
  function globalProfileDir() {
302941
- return join77(homedir21(), ".open-agents", "profiles");
303298
+ return join78(homedir22(), ".open-agents", "profiles");
302942
303299
  }
302943
303300
  function projectProfileDir(projectDir) {
302944
- return join77(projectDir || process.cwd(), ".oa", "profiles");
303301
+ return join78(projectDir || process.cwd(), ".oa", "profiles");
302945
303302
  }
302946
303303
  function listProfiles(projectDir) {
302947
303304
  const result = [];
302948
303305
  const seen = /* @__PURE__ */ new Set();
302949
303306
  const projDir = projectProfileDir(projectDir);
302950
- if (existsSync60(projDir)) {
303307
+ if (existsSync61(projDir)) {
302951
303308
  for (const f2 of readdirSync22(projDir).filter((f3) => f3.endsWith(".json"))) {
302952
303309
  try {
302953
- const raw = JSON.parse(readFileSync48(join77(projDir, f2), "utf8"));
303310
+ const raw = JSON.parse(readFileSync49(join78(projDir, f2), "utf8"));
302954
303311
  const name10 = f2.replace(".json", "");
302955
303312
  seen.add(name10);
302956
303313
  result.push({
@@ -302964,13 +303321,13 @@ function listProfiles(projectDir) {
302964
303321
  }
302965
303322
  }
302966
303323
  const globDir = globalProfileDir();
302967
- if (existsSync60(globDir)) {
303324
+ if (existsSync61(globDir)) {
302968
303325
  for (const f2 of readdirSync22(globDir).filter((f3) => f3.endsWith(".json"))) {
302969
303326
  const name10 = f2.replace(".json", "");
302970
303327
  if (seen.has(name10))
302971
303328
  continue;
302972
303329
  try {
302973
- const raw = JSON.parse(readFileSync48(join77(globDir, f2), "utf8"));
303330
+ const raw = JSON.parse(readFileSync49(join78(globDir, f2), "utf8"));
302974
303331
  result.push({
302975
303332
  name: name10,
302976
303333
  description: raw.description || "",
@@ -302985,12 +303342,12 @@ function listProfiles(projectDir) {
302985
303342
  }
302986
303343
  function loadProfile(name10, password, projectDir) {
302987
303344
  const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
302988
- const projPath = join77(projectProfileDir(projectDir), `${sanitized}.json`);
302989
- const globPath = join77(globalProfileDir(), `${sanitized}.json`);
302990
- const filePath = existsSync60(projPath) ? projPath : existsSync60(globPath) ? globPath : null;
303345
+ const projPath = join78(projectProfileDir(projectDir), `${sanitized}.json`);
303346
+ const globPath = join78(globalProfileDir(), `${sanitized}.json`);
303347
+ const filePath = existsSync61(projPath) ? projPath : existsSync61(globPath) ? globPath : null;
302991
303348
  if (!filePath)
302992
303349
  return null;
302993
- const raw = JSON.parse(readFileSync48(filePath, "utf8"));
303350
+ const raw = JSON.parse(readFileSync49(filePath, "utf8"));
302994
303351
  if (raw.encrypted === true) {
302995
303352
  if (!password)
302996
303353
  return null;
@@ -303000,24 +303357,24 @@ function loadProfile(name10, password, projectDir) {
303000
303357
  }
303001
303358
  function saveProfile(profile, password, scope = "global", projectDir) {
303002
303359
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
303003
- mkdirSync30(dir, { recursive: true });
303360
+ mkdirSync31(dir, { recursive: true });
303004
303361
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
303005
- const filePath = join77(dir, `${sanitized}.json`);
303362
+ const filePath = join78(dir, `${sanitized}.json`);
303006
303363
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
303007
303364
  if (password) {
303008
303365
  const encrypted = encryptProfile(profile, password);
303009
- writeFileSync28(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
303366
+ writeFileSync29(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
303010
303367
  } else {
303011
303368
  profile.encrypted = false;
303012
- writeFileSync28(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
303369
+ writeFileSync29(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
303013
303370
  }
303014
303371
  }
303015
303372
  function deleteProfile(name10, scope = "global", projectDir) {
303016
303373
  const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
303017
303374
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
303018
- const filePath = join77(dir, `${sanitized}.json`);
303019
- if (existsSync60(filePath)) {
303020
- unlinkSync12(filePath);
303375
+ const filePath = join78(dir, `${sanitized}.json`);
303376
+ if (existsSync61(filePath)) {
303377
+ unlinkSync13(filePath);
303021
303378
  return true;
303022
303379
  }
303023
303380
  return false;
@@ -303130,24 +303487,24 @@ var init_profiles = __esm({
303130
303487
  });
303131
303488
 
303132
303489
  // packages/cli/dist/docker.js
303133
- import { execSync as execSync37, spawn as spawn22 } from "node:child_process";
303134
- import { existsSync as existsSync61, mkdirSync as mkdirSync31, writeFileSync as writeFileSync29 } from "node:fs";
303135
- import { join as join78, resolve as resolve33, dirname as dirname22 } from "node:path";
303136
- import { homedir as homedir22 } from "node:os";
303137
- import { fileURLToPath as fileURLToPath14 } from "node:url";
303490
+ import { execSync as execSync37, spawn as spawn23 } from "node:child_process";
303491
+ import { existsSync as existsSync62, mkdirSync as mkdirSync32, writeFileSync as writeFileSync30 } from "node:fs";
303492
+ import { join as join79, resolve as resolve33, dirname as dirname23 } from "node:path";
303493
+ import { homedir as homedir23 } from "node:os";
303494
+ import { fileURLToPath as fileURLToPath15 } from "node:url";
303138
303495
  function getDockerDir() {
303139
303496
  try {
303140
303497
  if (typeof __dirname !== "undefined") {
303141
- return join78(__dirname, "..", "..", "..", "docker");
303498
+ return join79(__dirname, "..", "..", "..", "docker");
303142
303499
  }
303143
303500
  } catch {
303144
303501
  }
303145
303502
  try {
303146
- const thisDir = dirname22(fileURLToPath14(import.meta.url));
303147
- return join78(thisDir, "..", "..", "..", "docker");
303503
+ const thisDir = dirname23(fileURLToPath15(import.meta.url));
303504
+ return join79(thisDir, "..", "..", "..", "docker");
303148
303505
  } catch {
303149
303506
  }
303150
- return join78(process.cwd(), "docker");
303507
+ return join79(process.cwd(), "docker");
303151
303508
  }
303152
303509
  function isDockerAvailable() {
303153
303510
  try {
@@ -303278,11 +303635,11 @@ async function ensureOaImage(force = false) {
303278
303635
  }
303279
303636
  let buildContext;
303280
303637
  const dockerDir = getDockerDir();
303281
- if (existsSync61(join78(dockerDir, "Dockerfile"))) {
303638
+ if (existsSync62(join79(dockerDir, "Dockerfile"))) {
303282
303639
  buildContext = dockerDir;
303283
303640
  } else {
303284
- buildContext = join78(homedir22(), ".oa", "docker-build");
303285
- mkdirSync31(buildContext, { recursive: true });
303641
+ buildContext = join79(homedir23(), ".oa", "docker-build");
303642
+ mkdirSync32(buildContext, { recursive: true });
303286
303643
  writeDockerfiles(buildContext);
303287
303644
  }
303288
303645
  try {
@@ -303356,8 +303713,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
303356
303713
  if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
303357
303714
  exec "$@"
303358
303715
  `;
303359
- writeFileSync29(join78(dir, "Dockerfile"), dockerfile);
303360
- writeFileSync29(join78(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
303716
+ writeFileSync30(join79(dir, "Dockerfile"), dockerfile);
303717
+ writeFileSync30(join79(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
303361
303718
  }
303362
303719
  function hasNvidiaGpu() {
303363
303720
  try {
@@ -303414,7 +303771,7 @@ function runInContainer(opts) {
303414
303771
  if (opts.timeoutS)
303415
303772
  oaArgs.push("--timeout", String(opts.timeoutS));
303416
303773
  args.push(...oaArgs);
303417
- return spawn22("docker", args, {
303774
+ return spawn23("docker", args, {
303418
303775
  stdio: ["ignore", "pipe", "pipe"]
303419
303776
  });
303420
303777
  }
@@ -303436,23 +303793,23 @@ __export(serve_exports, {
303436
303793
  import * as http5 from "node:http";
303437
303794
  import * as https3 from "node:https";
303438
303795
  import { createRequire as createRequire4 } from "node:module";
303439
- import { fileURLToPath as fileURLToPath15 } from "node:url";
303440
- import { dirname as dirname23, join as join79, resolve as resolve34 } from "node:path";
303441
- import { spawn as spawn23, execSync as execSync38 } from "node:child_process";
303442
- import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30, readFileSync as readFileSync49, readdirSync as readdirSync23, existsSync as existsSync62 } from "node:fs";
303796
+ import { fileURLToPath as fileURLToPath16 } from "node:url";
303797
+ import { dirname as dirname24, join as join80, resolve as resolve34 } from "node:path";
303798
+ import { spawn as spawn24, execSync as execSync38 } from "node:child_process";
303799
+ import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync31, readFileSync as readFileSync50, readdirSync as readdirSync23, existsSync as existsSync63 } from "node:fs";
303443
303800
  import { randomBytes as randomBytes19, randomUUID as randomUUID5 } from "node:crypto";
303444
303801
  function getVersion3() {
303445
303802
  try {
303446
303803
  const require3 = createRequire4(import.meta.url);
303447
- const thisDir = dirname23(fileURLToPath15(import.meta.url));
303804
+ const thisDir = dirname24(fileURLToPath16(import.meta.url));
303448
303805
  const candidates = [
303449
- join79(thisDir, "..", "package.json"),
303450
- join79(thisDir, "..", "..", "package.json"),
303451
- join79(thisDir, "..", "..", "..", "package.json")
303806
+ join80(thisDir, "..", "package.json"),
303807
+ join80(thisDir, "..", "..", "package.json"),
303808
+ join80(thisDir, "..", "..", "..", "package.json")
303452
303809
  ];
303453
303810
  for (const pkgPath of candidates) {
303454
303811
  try {
303455
- if (!existsSync62(pkgPath))
303812
+ if (!existsSync63(pkgPath))
303456
303813
  continue;
303457
303814
  const pkg = require3(pkgPath);
303458
303815
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
@@ -303753,29 +304110,29 @@ function ollamaStream(ollamaUrl, path5, method, body, onData, onEnd, onError) {
303753
304110
  }
303754
304111
  function jobsDir() {
303755
304112
  const root = resolve34(process.cwd());
303756
- const dir = join79(root, ".oa", "jobs");
303757
- mkdirSync32(dir, { recursive: true });
304113
+ const dir = join80(root, ".oa", "jobs");
304114
+ mkdirSync33(dir, { recursive: true });
303758
304115
  return dir;
303759
304116
  }
303760
304117
  function loadJob(id) {
303761
- const file = join79(jobsDir(), `${id}.json`);
303762
- if (!existsSync62(file))
304118
+ const file = join80(jobsDir(), `${id}.json`);
304119
+ if (!existsSync63(file))
303763
304120
  return null;
303764
304121
  try {
303765
- return JSON.parse(readFileSync49(file, "utf-8"));
304122
+ return JSON.parse(readFileSync50(file, "utf-8"));
303766
304123
  } catch {
303767
304124
  return null;
303768
304125
  }
303769
304126
  }
303770
304127
  function listJobs() {
303771
304128
  const dir = jobsDir();
303772
- if (!existsSync62(dir))
304129
+ if (!existsSync63(dir))
303773
304130
  return [];
303774
304131
  const files = readdirSync23(dir).filter((f2) => f2.endsWith(".json")).sort();
303775
304132
  const jobs = [];
303776
304133
  for (const file of files) {
303777
304134
  try {
303778
- jobs.push(JSON.parse(readFileSync49(join79(dir, file), "utf-8")));
304135
+ jobs.push(JSON.parse(readFileSync50(join80(dir, file), "utf-8")));
303779
304136
  } catch {
303780
304137
  }
303781
304138
  }
@@ -304250,8 +304607,8 @@ async function handleV1Run(req2, res) {
304250
304607
  if (workingDir) {
304251
304608
  cwd4 = resolve34(workingDir);
304252
304609
  } else if (isolate) {
304253
- const wsDir = join79(dir, "..", "workspaces", id);
304254
- mkdirSync32(wsDir, { recursive: true });
304610
+ const wsDir = join80(dir, "..", "workspaces", id);
304611
+ mkdirSync33(wsDir, { recursive: true });
304255
304612
  cwd4 = wsDir;
304256
304613
  } else {
304257
304614
  cwd4 = resolve34(process.cwd());
@@ -304329,7 +304686,7 @@ async function handleV1Run(req2, res) {
304329
304686
  });
304330
304687
  job.sandbox = "container";
304331
304688
  } else {
304332
- child = spawn23(process.execPath, [oaBin, ...args], {
304689
+ child = spawn24(process.execPath, [oaBin, ...args], {
304333
304690
  cwd: cwd4,
304334
304691
  env: runEnv,
304335
304692
  stdio: ["ignore", "pipe", "pipe"],
@@ -304339,7 +304696,7 @@ async function handleV1Run(req2, res) {
304339
304696
  job.sandbox = sandbox;
304340
304697
  }
304341
304698
  job.pid = child.pid ?? 0;
304342
- writeFileSync30(join79(dir, `${id}.json`), JSON.stringify(job, null, 2));
304699
+ writeFileSync31(join80(dir, `${id}.json`), JSON.stringify(job, null, 2));
304343
304700
  runningProcesses.set(id, child);
304344
304701
  if (streamMode) {
304345
304702
  res.writeHead(200, {
@@ -304366,7 +304723,7 @@ async function handleV1Run(req2, res) {
304366
304723
  job.status = code8 === 0 ? "completed" : "failed";
304367
304724
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
304368
304725
  try {
304369
- writeFileSync30(join79(dir, `${id}.json`), JSON.stringify(job, null, 2));
304726
+ writeFileSync31(join80(dir, `${id}.json`), JSON.stringify(job, null, 2));
304370
304727
  } catch {
304371
304728
  }
304372
304729
  runningProcesses.delete(id);
@@ -304406,7 +304763,7 @@ async function handleV1Run(req2, res) {
304406
304763
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
304407
304764
  }
304408
304765
  try {
304409
- writeFileSync30(join79(dir, `${id}.json`), JSON.stringify(job, null, 2));
304766
+ writeFileSync31(join80(dir, `${id}.json`), JSON.stringify(job, null, 2));
304410
304767
  } catch {
304411
304768
  }
304412
304769
  runningProcesses.delete(id);
@@ -304475,7 +304832,7 @@ function handleV1RunsDelete(res, id) {
304475
304832
  job.error = "Aborted via API";
304476
304833
  const dir = jobsDir();
304477
304834
  try {
304478
- writeFileSync30(join79(dir, `${id}.json`), JSON.stringify(job, null, 2));
304835
+ writeFileSync31(join80(dir, `${id}.json`), JSON.stringify(job, null, 2));
304479
304836
  } catch {
304480
304837
  }
304481
304838
  runningProcesses.delete(id);
@@ -304587,7 +304944,7 @@ async function handlePostCommand(res, cmd) {
304587
304944
  return;
304588
304945
  }
304589
304946
  try {
304590
- const child = spawn23("node", [oaBin, "run", `/${cmd}`, "--json"], {
304947
+ const child = spawn24("node", [oaBin, "run", `/${cmd}`, "--json"], {
304591
304948
  env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
304592
304949
  stdio: ["ignore", "pipe", "pipe"],
304593
304950
  timeout: 3e4
@@ -304797,7 +305154,7 @@ ${historyLines}
304797
305154
  };
304798
305155
  if (currentCfg.apiKey)
304799
305156
  runEnv["OA_API_KEY_INHERIT"] = currentCfg.apiKey;
304800
- const child = spawn23(process.execPath, [oaBin, ...args], {
305157
+ const child = spawn24(process.execPath, [oaBin, ...args], {
304801
305158
  cwd: cwdPath,
304802
305159
  env: runEnv,
304803
305160
  stdio: ["ignore", "pipe", "pipe"]
@@ -305168,24 +305525,24 @@ function startApiServer(options2 = {}) {
305168
305525
  const config = loadConfig();
305169
305526
  const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
305170
305527
  const cwd4 = process.cwd();
305171
- initAuditLog(join79(cwd4, ".oa"));
305172
- initUsageTracker(join79(cwd4, ".oa"));
305528
+ initAuditLog(join80(cwd4, ".oa"));
305529
+ initUsageTracker(join80(cwd4, ".oa"));
305173
305530
  const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
305174
305531
  if (retentionDays > 0) {
305175
305532
  try {
305176
- const jobsDir3 = join79(cwd4, ".oa", "jobs");
305177
- if (existsSync62(jobsDir3)) {
305533
+ const jobsDir3 = join80(cwd4, ".oa", "jobs");
305534
+ if (existsSync63(jobsDir3)) {
305178
305535
  const cutoff = Date.now() - retentionDays * 864e5;
305179
305536
  for (const f2 of readdirSync23(jobsDir3)) {
305180
305537
  if (!f2.endsWith(".json"))
305181
305538
  continue;
305182
305539
  try {
305183
- const jobPath = join79(jobsDir3, f2);
305184
- const job = JSON.parse(readFileSync49(jobPath, "utf-8"));
305540
+ const jobPath = join80(jobsDir3, f2);
305541
+ const job = JSON.parse(readFileSync50(jobPath, "utf-8"));
305185
305542
  const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
305186
305543
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
305187
- const { unlinkSync: unlinkSync13 } = __require("node:fs");
305188
- unlinkSync13(jobPath);
305544
+ const { unlinkSync: unlinkSync14 } = __require("node:fs");
305545
+ unlinkSync14(jobPath);
305189
305546
  }
305190
305547
  } catch {
305191
305548
  }
@@ -305201,8 +305558,8 @@ function startApiServer(options2 = {}) {
305201
305558
  if (useTls) {
305202
305559
  try {
305203
305560
  tlsOpts = {
305204
- cert: readFileSync49(resolve34(tlsCert)),
305205
- key: readFileSync49(resolve34(tlsKey))
305561
+ cert: readFileSync50(resolve34(tlsCert)),
305562
+ key: readFileSync50(resolve34(tlsKey))
305206
305563
  };
305207
305564
  } catch (e2) {
305208
305565
  log22(`
@@ -305401,13 +305758,13 @@ var init_serve = __esm({
305401
305758
 
305402
305759
  // packages/cli/dist/tui/interactive.js
305403
305760
  import { cwd } from "node:process";
305404
- import { resolve as resolve35, join as join80, dirname as dirname24, extname as extname11 } from "node:path";
305761
+ import { resolve as resolve35, join as join81, dirname as dirname25, extname as extname11 } from "node:path";
305405
305762
  import { createRequire as createRequire5 } from "node:module";
305406
- import { fileURLToPath as fileURLToPath16 } from "node:url";
305407
- import { readFileSync as readFileSync50, writeFileSync as writeFileSync31, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync24, mkdirSync as mkdirSync33 } from "node:fs";
305408
- import { existsSync as existsSync63 } from "node:fs";
305763
+ import { fileURLToPath as fileURLToPath17 } from "node:url";
305764
+ import { readFileSync as readFileSync51, writeFileSync as writeFileSync32, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync24, mkdirSync as mkdirSync34 } from "node:fs";
305765
+ import { existsSync as existsSync64 } from "node:fs";
305409
305766
  import { execSync as execSync39 } from "node:child_process";
305410
- import { homedir as homedir23 } from "node:os";
305767
+ import { homedir as homedir24 } from "node:os";
305411
305768
  function formatTimeAgo(date) {
305412
305769
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
305413
305770
  if (seconds < 60)
@@ -305424,14 +305781,14 @@ function formatTimeAgo(date) {
305424
305781
  function getVersion4() {
305425
305782
  try {
305426
305783
  const require3 = createRequire5(import.meta.url);
305427
- const thisDir = dirname24(fileURLToPath16(import.meta.url));
305784
+ const thisDir = dirname25(fileURLToPath17(import.meta.url));
305428
305785
  const candidates = [
305429
- join80(thisDir, "..", "package.json"),
305430
- join80(thisDir, "..", "..", "package.json"),
305431
- join80(thisDir, "..", "..", "..", "package.json")
305786
+ join81(thisDir, "..", "package.json"),
305787
+ join81(thisDir, "..", "..", "package.json"),
305788
+ join81(thisDir, "..", "..", "..", "package.json")
305432
305789
  ];
305433
305790
  for (const pkgPath of candidates) {
305434
- if (existsSync63(pkgPath)) {
305791
+ if (existsSync64(pkgPath)) {
305435
305792
  const pkg = require3(pkgPath);
305436
305793
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
305437
305794
  return pkg.version ?? "0.0.0";
@@ -305885,15 +306242,15 @@ Meta-critique: quality ${meta.quality}/5, thorough: ${meta.thorough}`;
305885
306242
  function gatherMemorySnippets(root) {
305886
306243
  const snippets = [];
305887
306244
  const dirs = [
305888
- join80(root, ".oa", "memory"),
305889
- join80(root, ".open-agents", "memory")
306245
+ join81(root, ".oa", "memory"),
306246
+ join81(root, ".open-agents", "memory")
305890
306247
  ];
305891
306248
  for (const dir of dirs) {
305892
- if (!existsSync63(dir))
306249
+ if (!existsSync64(dir))
305893
306250
  continue;
305894
306251
  try {
305895
306252
  for (const f2 of readdirSync24(dir).filter((f3) => f3.endsWith(".json"))) {
305896
- const data = JSON.parse(readFileSync50(join80(dir, f2), "utf-8"));
306253
+ const data = JSON.parse(readFileSync51(join81(dir, f2), "utf-8"));
305897
306254
  for (const val of Object.values(data)) {
305898
306255
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
305899
306256
  if (v.length > 10)
@@ -306050,9 +306407,9 @@ ${metabolismMemories}
306050
306407
  } catch {
306051
306408
  }
306052
306409
  try {
306053
- const archeFile = join80(repoRoot, ".oa", "arche", "variants.json");
306054
- if (existsSync63(archeFile)) {
306055
- const variants = JSON.parse(readFileSync50(archeFile, "utf8"));
306410
+ const archeFile = join81(repoRoot, ".oa", "arche", "variants.json");
306411
+ if (existsSync64(archeFile)) {
306412
+ const variants = JSON.parse(readFileSync51(archeFile, "utf8"));
306056
306413
  if (variants.length > 0) {
306057
306414
  let filtered = variants;
306058
306415
  if (taskType) {
@@ -306221,9 +306578,9 @@ RULES:
306221
306578
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
306222
306579
  let identityInjection = "";
306223
306580
  try {
306224
- const ikStateFile = join80(repoRoot, ".oa", "identity", "self-state.json");
306225
- if (existsSync63(ikStateFile)) {
306226
- const selfState = JSON.parse(readFileSync50(ikStateFile, "utf8"));
306581
+ const ikStateFile = join81(repoRoot, ".oa", "identity", "self-state.json");
306582
+ if (existsSync64(ikStateFile)) {
306583
+ const selfState = JSON.parse(readFileSync51(ikStateFile, "utf8"));
306227
306584
  const lines = [
306228
306585
  `[Identity State v${selfState.version}]`,
306229
306586
  `Self: ${selfState.narrative_summary}`,
@@ -306889,13 +307246,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
306889
307246
  });
306890
307247
  }
306891
307248
  try {
306892
- const ikDir = join80(repoRoot, ".oa", "identity");
306893
- const ikFile = join80(ikDir, "self-state.json");
307249
+ const ikDir = join81(repoRoot, ".oa", "identity");
307250
+ const ikFile = join81(ikDir, "self-state.json");
306894
307251
  let ikState;
306895
- if (existsSync63(ikFile)) {
306896
- ikState = JSON.parse(readFileSync50(ikFile, "utf8"));
307252
+ if (existsSync64(ikFile)) {
307253
+ ikState = JSON.parse(readFileSync51(ikFile, "utf8"));
306897
307254
  } else {
306898
- mkdirSync33(ikDir, { recursive: true });
307255
+ mkdirSync34(ikDir, { recursive: true });
306899
307256
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
306900
307257
  ikState = {
306901
307258
  self_id: `oa-${machineId}`,
@@ -306956,7 +307313,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
306956
307313
  }
306957
307314
  ikState.session_count = (ikState.session_count || 0) + 1;
306958
307315
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
306959
- writeFileSync31(ikFile, JSON.stringify(ikState, null, 2));
307316
+ writeFileSync32(ikFile, JSON.stringify(ikState, null, 2));
306960
307317
  } catch (ikErr) {
306961
307318
  try {
306962
307319
  console.error("[IK-OBSERVE]", ikErr);
@@ -306971,9 +307328,9 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
306971
307328
  } else {
306972
307329
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
306973
307330
  try {
306974
- const ikFile = join80(repoRoot, ".oa", "identity", "self-state.json");
306975
- if (existsSync63(ikFile)) {
306976
- const ikState = JSON.parse(readFileSync50(ikFile, "utf8"));
307331
+ const ikFile = join81(repoRoot, ".oa", "identity", "self-state.json");
307332
+ if (existsSync64(ikFile)) {
307333
+ const ikState = JSON.parse(readFileSync51(ikFile, "utf8"));
306977
307334
  if (!ikState.stats)
306978
307335
  ikState.stats = { queries_served: 0 };
306979
307336
  ikState.stats.queries_served = (ikState.stats.queries_served || 0) + 1;
@@ -306987,7 +307344,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
306987
307344
  ikState.version_history = ikState.version_history.slice(-200);
306988
307345
  ikState.session_count = (ikState.session_count || 0) + 1;
306989
307346
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
306990
- writeFileSync31(ikFile, JSON.stringify(ikState, null, 2));
307347
+ writeFileSync32(ikFile, JSON.stringify(ikState, null, 2));
306991
307348
  }
306992
307349
  } catch {
306993
307350
  }
@@ -307084,10 +307441,10 @@ async function startInteractive(config, repoPath) {
307084
307441
  process.stdin.pause();
307085
307442
  }
307086
307443
  try {
307087
- const oaDir = join80(repoRoot, ".oa");
307088
- const nexusPidFile = join80(oaDir, "nexus", "daemon.pid");
307089
- if (existsSync63(nexusPidFile)) {
307090
- const pid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
307444
+ const oaDir = join81(repoRoot, ".oa");
307445
+ const nexusPidFile = join81(oaDir, "nexus", "daemon.pid");
307446
+ if (existsSync64(nexusPidFile)) {
307447
+ const pid = parseInt(readFileSync51(nexusPidFile, "utf8").trim(), 10);
307091
307448
  if (pid > 0) {
307092
307449
  try {
307093
307450
  process.kill(pid, 0);
@@ -307581,7 +307938,7 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
307581
307938
  let p2pGateway = null;
307582
307939
  let peerMesh = null;
307583
307940
  let inferenceRouter = null;
307584
- const secretVault = new SecretVault(join80(repoRoot, ".oa", "vault.enc"));
307941
+ const secretVault = new SecretVault(join81(repoRoot, ".oa", "vault.enc"));
307585
307942
  let adminSessionKey = null;
307586
307943
  const callSubAgents = /* @__PURE__ */ new Map();
307587
307944
  const streamRenderer = new StreamRenderer();
@@ -307804,13 +308161,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
307804
308161
  const hits = allCompletions.filter((c4) => c4.toLowerCase().startsWith(lower));
307805
308162
  return [hits, line];
307806
308163
  }
307807
- const HISTORY_DIR = join80(homedir23(), ".open-agents");
307808
- const HISTORY_FILE = join80(HISTORY_DIR, "repl-history");
308164
+ const HISTORY_DIR = join81(homedir24(), ".open-agents");
308165
+ const HISTORY_FILE = join81(HISTORY_DIR, "repl-history");
307809
308166
  const MAX_HISTORY_LINES = 500;
307810
308167
  let savedHistory = [];
307811
308168
  try {
307812
- if (existsSync63(HISTORY_FILE)) {
307813
- const raw = readFileSync50(HISTORY_FILE, "utf8").trim();
308169
+ if (existsSync64(HISTORY_FILE)) {
308170
+ const raw = readFileSync51(HISTORY_FILE, "utf8").trim();
307814
308171
  if (raw)
307815
308172
  savedHistory = raw.split("\n").reverse();
307816
308173
  }
@@ -307913,12 +308270,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
307913
308270
  if (!line.trim())
307914
308271
  return;
307915
308272
  try {
307916
- mkdirSync33(HISTORY_DIR, { recursive: true });
308273
+ mkdirSync34(HISTORY_DIR, { recursive: true });
307917
308274
  appendFileSync6(HISTORY_FILE, line + "\n", "utf8");
307918
308275
  if (Math.random() < 0.02) {
307919
- const all2 = readFileSync50(HISTORY_FILE, "utf8").trim().split("\n");
308276
+ const all2 = readFileSync51(HISTORY_FILE, "utf8").trim().split("\n");
307920
308277
  if (all2.length > MAX_HISTORY_LINES) {
307921
- writeFileSync31(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
308278
+ writeFileSync32(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
307922
308279
  }
307923
308280
  }
307924
308281
  } catch {
@@ -308095,10 +308452,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308095
308452
  const { unlinkSync: _rmStale } = await import("node:fs");
308096
308453
  const { homedir: _hdir } = await import("node:os");
308097
308454
  for (const dp of [
308098
- join80(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
308099
- join80(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
308455
+ join81(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
308456
+ join81(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
308100
308457
  ]) {
308101
- if (existsSync63(dp))
308458
+ if (existsSync64(dp))
308102
308459
  try {
308103
308460
  _rmStale(dp);
308104
308461
  } catch {
@@ -308110,9 +308467,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308110
308467
  const autoNexus = new NexusTool(repoRoot);
308111
308468
  const _registerNexusDaemon = () => {
308112
308469
  try {
308113
- const nexusPidFile = join80(repoRoot, ".oa", "nexus", "daemon.pid");
308114
- if (existsSync63(nexusPidFile)) {
308115
- const nPid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
308470
+ const nexusPidFile = join81(repoRoot, ".oa", "nexus", "daemon.pid");
308471
+ if (existsSync64(nexusPidFile)) {
308472
+ const nPid = parseInt(readFileSync51(nexusPidFile, "utf8").trim(), 10);
308116
308473
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
308117
308474
  registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
308118
308475
  statusBar.ensureMonitorTimer();
@@ -308153,7 +308510,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308153
308510
  } catch {
308154
308511
  }
308155
308512
  try {
308156
- const oaDir = join80(repoRoot, ".oa");
308513
+ const oaDir = join81(repoRoot, ".oa");
308157
308514
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
308158
308515
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
308159
308516
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -308185,7 +308542,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308185
308542
  } catch {
308186
308543
  }
308187
308544
  try {
308188
- const oaDir = join80(repoRoot, ".oa");
308545
+ const oaDir = join81(repoRoot, ".oa");
308189
308546
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
308190
308547
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
308191
308548
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -308226,11 +308583,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308226
308583
  }
308227
308584
  try {
308228
308585
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
308229
- const globalNamePath = join80(_hd(), ".open-agents", "agent-name");
308586
+ const globalNamePath = join81(_hd(), ".open-agents", "agent-name");
308230
308587
  let agName = "";
308231
308588
  try {
308232
- if (existsSync63(globalNamePath))
308233
- agName = readFileSync50(globalNamePath, "utf8").trim();
308589
+ if (existsSync64(globalNamePath))
308590
+ agName = readFileSync51(globalNamePath, "utf8").trim();
308234
308591
  } catch {
308235
308592
  }
308236
308593
  if (!agName) {
@@ -308259,11 +308616,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308259
308616
  }
308260
308617
  if (!ollamaAlive) {
308261
308618
  try {
308262
- const savedSponsorsPath = join80(repoRoot, ".oa", "sponsor", "known-sponsors.json");
308619
+ const savedSponsorsPath = join81(repoRoot, ".oa", "sponsor", "known-sponsors.json");
308263
308620
  let savedSponsors = [];
308264
308621
  try {
308265
- if (existsSync63(savedSponsorsPath)) {
308266
- savedSponsors = JSON.parse(readFileSync50(savedSponsorsPath, "utf8"));
308622
+ if (existsSync64(savedSponsorsPath)) {
308623
+ savedSponsors = JSON.parse(readFileSync51(savedSponsorsPath, "utf8"));
308267
308624
  const oneHourAgo = Date.now() - 36e5;
308268
308625
  savedSponsors = savedSponsors.filter((s2) => (s2.lastVerified || 0) > oneHourAgo);
308269
308626
  }
@@ -308327,18 +308684,33 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
308327
308684
  });
308328
308685
  setupTasks.push(startupChecksPromise.catch(() => {
308329
308686
  }));
308330
- Promise.resolve().then(() => (init_serve(), serve_exports)).then(({ startApiServer: startApiServer2 }) => {
308687
+ Promise.resolve().then(() => (init_daemon(), daemon_exports)).then(async ({ ensureDaemon: ensureDaemon2, isDaemonRunning: isDaemonRunning2 }) => {
308331
308688
  const apiPort = parseInt(process.env["OA_PORT"] || "11435", 10);
308689
+ if (await isDaemonRunning2(apiPort)) {
308690
+ setTimeout(() => {
308691
+ if (statusBar.isActive)
308692
+ writeContent(() => renderInfo(`REST API: http://localhost:${apiPort} (shared daemon)`));
308693
+ }, 1500);
308694
+ return;
308695
+ }
308696
+ const daemonOk = await ensureDaemon2();
308697
+ if (daemonOk) {
308698
+ setTimeout(() => {
308699
+ if (statusBar.isActive)
308700
+ writeContent(() => renderInfo(`REST API: http://localhost:${apiPort} (daemon started)`));
308701
+ }, 1500);
308702
+ return;
308703
+ }
308704
+ const { startApiServer: startApiServer2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
308332
308705
  const apiServer = startApiServer2({
308333
308706
  port: apiPort,
308334
308707
  ollamaUrl: currentConfig.backendUrl || "http://127.0.0.1:11434",
308335
308708
  quiet: true
308336
- // TUI mode — suppress all direct stderr/stdout output
308337
308709
  });
308338
308710
  apiServer.on?.("listening", () => {
308339
308711
  setTimeout(() => {
308340
308712
  if (statusBar.isActive)
308341
- writeContent(() => renderInfo(`REST API: http://localhost:${apiPort}`));
308713
+ writeContent(() => renderInfo(`REST API: http://localhost:${apiPort} (inline \u2014 daemon unavailable)`));
308342
308714
  }, 1500);
308343
308715
  });
308344
308716
  apiServer.on?.("error", () => {
@@ -309223,7 +309595,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309223
309595
  kind,
309224
309596
  targetUrl,
309225
309597
  authKey,
309226
- stateDir: join80(repoRoot, ".oa"),
309598
+ stateDir: join81(repoRoot, ".oa"),
309227
309599
  passthrough: passthrough ?? false,
309228
309600
  loadbalance: loadbalance ?? false,
309229
309601
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -309269,7 +309641,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309269
309641
  await tunnelGateway.stop();
309270
309642
  tunnelGateway = null;
309271
309643
  }
309272
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join80(repoRoot, ".oa") });
309644
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join81(repoRoot, ".oa") });
309273
309645
  newTunnel.on("stats", (stats) => {
309274
309646
  statusBar.setExposeStatus({
309275
309647
  status: stats.status,
@@ -309358,9 +309730,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309358
309730
  if (!result.success)
309359
309731
  throw new Error(result.error || "Connect failed");
309360
309732
  try {
309361
- const nexusPidFile = join80(repoRoot, ".oa", "nexus", "daemon.pid");
309362
- if (existsSync63(nexusPidFile)) {
309363
- const pid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
309733
+ const nexusPidFile = join81(repoRoot, ".oa", "nexus", "daemon.pid");
309734
+ if (existsSync64(nexusPidFile)) {
309735
+ const pid = parseInt(readFileSync51(nexusPidFile, "utf8").trim(), 10);
309364
309736
  if (pid > 0) {
309365
309737
  registry2.register({
309366
309738
  name: "Nexus",
@@ -309556,10 +309928,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309556
309928
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
309557
309929
  }
309558
309930
  try {
309559
- const nexusDir = join80(repoRoot, OA_DIR, "nexus");
309560
- const pidFile = join80(nexusDir, "daemon.pid");
309561
- if (existsSync63(pidFile)) {
309562
- const pid = parseInt(readFileSync50(pidFile, "utf8").trim(), 10);
309931
+ const nexusDir = join81(repoRoot, OA_DIR, "nexus");
309932
+ const pidFile = join81(nexusDir, "daemon.pid");
309933
+ if (existsSync64(pidFile)) {
309934
+ const pid = parseInt(readFileSync51(pidFile, "utf8").trim(), 10);
309563
309935
  if (pid > 0) {
309564
309936
  try {
309565
309937
  if (process.platform === "win32") {
@@ -309581,13 +309953,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309581
309953
  } catch {
309582
309954
  }
309583
309955
  try {
309584
- const voiceDir2 = join80(homedir23(), ".open-agents", "voice");
309956
+ const voiceDir2 = join81(homedir24(), ".open-agents", "voice");
309585
309957
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
309586
309958
  for (const pf of voicePidFiles) {
309587
- const pidPath = join80(voiceDir2, pf);
309588
- if (existsSync63(pidPath)) {
309959
+ const pidPath = join81(voiceDir2, pf);
309960
+ if (existsSync64(pidPath)) {
309589
309961
  try {
309590
- const pid = parseInt(readFileSync50(pidPath, "utf8").trim(), 10);
309962
+ const pid = parseInt(readFileSync51(pidPath, "utf8").trim(), 10);
309591
309963
  if (pid > 0) {
309592
309964
  if (process.platform === "win32") {
309593
309965
  try {
@@ -309611,8 +309983,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309611
309983
  execSync39(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
309612
309984
  } catch {
309613
309985
  }
309614
- const oaPath = join80(repoRoot, OA_DIR);
309615
- if (existsSync63(oaPath)) {
309986
+ const oaPath = join81(repoRoot, OA_DIR);
309987
+ if (existsSync64(oaPath)) {
309616
309988
  let deleted = false;
309617
309989
  for (let attempt = 0; attempt < 3; attempt++) {
309618
309990
  try {
@@ -309695,19 +310067,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
309695
310067
  try {
309696
310068
  const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
309697
310069
  if (isPersonaPlexRunning2()) {
309698
- const ppPidFile = join80(homedir23(), ".open-agents", "voice", "personaplex", "daemon.pid");
309699
- const ppPortFile = join80(homedir23(), ".open-agents", "voice", "personaplex", "daemon.port");
309700
- if (existsSync63(ppPidFile)) {
309701
- const ppPid = parseInt(readFileSync50(ppPidFile, "utf8").trim(), 10);
309702
- const ppPort = existsSync63(ppPortFile) ? parseInt(readFileSync50(ppPortFile, "utf8").trim(), 10) : void 0;
310070
+ const ppPidFile = join81(homedir24(), ".open-agents", "voice", "personaplex", "daemon.pid");
310071
+ const ppPortFile = join81(homedir24(), ".open-agents", "voice", "personaplex", "daemon.port");
310072
+ if (existsSync64(ppPidFile)) {
310073
+ const ppPid = parseInt(readFileSync51(ppPidFile, "utf8").trim(), 10);
310074
+ const ppPort = existsSync64(ppPortFile) ? parseInt(readFileSync51(ppPortFile, "utf8").trim(), 10) : void 0;
309703
310075
  if (ppPid > 0 && !registry2.daemons.has("PersonaPlex")) {
309704
310076
  registry2.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
309705
310077
  }
309706
310078
  }
309707
310079
  }
309708
- const nexusPidFile = join80(repoRoot, ".oa", "nexus", "daemon.pid");
309709
- if (existsSync63(nexusPidFile)) {
309710
- const nPid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
310080
+ const nexusPidFile = join81(repoRoot, ".oa", "nexus", "daemon.pid");
310081
+ if (existsSync64(nexusPidFile)) {
310082
+ const nPid = parseInt(readFileSync51(nexusPidFile, "utf8").trim(), 10);
309711
310083
  if (nPid > 0 && !registry2.daemons.has("Nexus")) {
309712
310084
  try {
309713
310085
  process.kill(nPid, 0);
@@ -310049,8 +310421,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
310049
310421
  }
310050
310422
  }
310051
310423
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
310052
- const isImage = isImagePath(cleanPath) && existsSync63(resolve35(repoRoot, cleanPath));
310053
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync63(resolve35(repoRoot, cleanPath));
310424
+ const isImage = isImagePath(cleanPath) && existsSync64(resolve35(repoRoot, cleanPath));
310425
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync64(resolve35(repoRoot, cleanPath));
310054
310426
  if (activeTask) {
310055
310427
  if (activeTask.runner.isPaused) {
310056
310428
  activeTask.runner.resume();
@@ -310059,7 +310431,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
310059
310431
  if (isImage) {
310060
310432
  try {
310061
310433
  const imgPath = resolve35(repoRoot, cleanPath);
310062
- const imgBuffer = readFileSync50(imgPath);
310434
+ const imgBuffer = readFileSync51(imgPath);
310063
310435
  const base642 = imgBuffer.toString("base64");
310064
310436
  const ext = extname11(cleanPath).toLowerCase();
310065
310437
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -310274,7 +310646,7 @@ Summarize or analyze this transcription as appropriate.`;
310274
310646
 
310275
310647
  NEW TASK: ${fullInput}`;
310276
310648
  restoredSessionContext = null;
310277
- } else if (existsSync63(join80(repoRoot, ".oa", "context", "session-diary.md"))) {
310649
+ } else if (existsSync64(join81(repoRoot, ".oa", "context", "session-diary.md"))) {
310278
310650
  taskInput = `[Previous sessions exist \u2014 file_read(".oa/context/session-diary.md") to recall]
310279
310651
 
310280
310652
  ${fullInput}`;
@@ -310592,13 +310964,13 @@ async function runWithTUI(task, config, repoPath, callbacks) {
310592
310964
  const handle2 = startTask(task, config, repoRoot);
310593
310965
  await handle2.promise;
310594
310966
  try {
310595
- const ikDir = join80(repoRoot, ".oa", "identity");
310596
- const ikFile = join80(ikDir, "self-state.json");
310967
+ const ikDir = join81(repoRoot, ".oa", "identity");
310968
+ const ikFile = join81(ikDir, "self-state.json");
310597
310969
  let ikState;
310598
- if (existsSync63(ikFile)) {
310599
- ikState = JSON.parse(readFileSync50(ikFile, "utf8"));
310970
+ if (existsSync64(ikFile)) {
310971
+ ikState = JSON.parse(readFileSync51(ikFile, "utf8"));
310600
310972
  } else {
310601
- mkdirSync33(ikDir, { recursive: true });
310973
+ mkdirSync34(ikDir, { recursive: true });
310602
310974
  ikState = {
310603
310975
  self_id: `oa-${Date.now().toString(36)}`,
310604
310976
  version: 1,
@@ -310620,7 +310992,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
310620
310992
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
310621
310993
  ikState.session_count = (ikState.session_count || 0) + 1;
310622
310994
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
310623
- writeFileSync31(ikFile, JSON.stringify(ikState, null, 2));
310995
+ writeFileSync32(ikFile, JSON.stringify(ikState, null, 2));
310624
310996
  } catch (ikErr) {
310625
310997
  }
310626
310998
  try {
@@ -310629,12 +311001,12 @@ async function runWithTUI(task, config, repoPath, callbacks) {
310629
311001
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
310630
311002
  } catch {
310631
311003
  try {
310632
- const archeDir = join80(repoRoot, ".oa", "arche");
310633
- const archeFile = join80(archeDir, "variants.json");
311004
+ const archeDir = join81(repoRoot, ".oa", "arche");
311005
+ const archeFile = join81(archeDir, "variants.json");
310634
311006
  let variants = [];
310635
311007
  try {
310636
- if (existsSync63(archeFile))
310637
- variants = JSON.parse(readFileSync50(archeFile, "utf8"));
311008
+ if (existsSync64(archeFile))
311009
+ variants = JSON.parse(readFileSync51(archeFile, "utf8"));
310638
311010
  } catch {
310639
311011
  }
310640
311012
  variants.push({
@@ -310649,15 +311021,15 @@ async function runWithTUI(task, config, repoPath, callbacks) {
310649
311021
  });
310650
311022
  if (variants.length > 50)
310651
311023
  variants = variants.slice(-50);
310652
- mkdirSync33(archeDir, { recursive: true });
310653
- writeFileSync31(archeFile, JSON.stringify(variants, null, 2));
311024
+ mkdirSync34(archeDir, { recursive: true });
311025
+ writeFileSync32(archeFile, JSON.stringify(variants, null, 2));
310654
311026
  } catch {
310655
311027
  }
310656
311028
  }
310657
311029
  try {
310658
- const metaFile = join80(repoRoot, ".oa", "memory", "metabolism", "store.json");
310659
- if (existsSync63(metaFile)) {
310660
- const store2 = JSON.parse(readFileSync50(metaFile, "utf8"));
311030
+ const metaFile = join81(repoRoot, ".oa", "memory", "metabolism", "store.json");
311031
+ if (existsSync64(metaFile)) {
311032
+ const store2 = JSON.parse(readFileSync51(metaFile, "utf8"));
310661
311033
  const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
310662
311034
  let updated = false;
310663
311035
  for (const item of surfaced) {
@@ -310668,7 +311040,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
310668
311040
  updated = true;
310669
311041
  }
310670
311042
  if (updated) {
310671
- writeFileSync31(metaFile, JSON.stringify(store2, null, 2));
311043
+ writeFileSync32(metaFile, JSON.stringify(store2, null, 2));
310672
311044
  }
310673
311045
  }
310674
311046
  } catch {
@@ -310721,9 +311093,9 @@ Rules:
310721
311093
  try {
310722
311094
  const { initDb: initDb2 } = __require("@open-agents/memory");
310723
311095
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
310724
- const dbDir = join80(repoRoot, ".oa", "memory");
310725
- mkdirSync33(dbDir, { recursive: true });
310726
- const db = initDb2(join80(dbDir, "structured.db"));
311096
+ const dbDir = join81(repoRoot, ".oa", "memory");
311097
+ mkdirSync34(dbDir, { recursive: true });
311098
+ const db = initDb2(join81(dbDir, "structured.db"));
310727
311099
  const memStore = new ProceduralMemoryStore2(db);
310728
311100
  memStore.createWithEmbedding({
310729
311101
  content: content.slice(0, 600),
@@ -310738,12 +311110,12 @@ Rules:
310738
311110
  db.close();
310739
311111
  } catch {
310740
311112
  }
310741
- const metaDir = join80(repoRoot, ".oa", "memory", "metabolism");
310742
- const storeFile = join80(metaDir, "store.json");
311113
+ const metaDir = join81(repoRoot, ".oa", "memory", "metabolism");
311114
+ const storeFile = join81(metaDir, "store.json");
310743
311115
  let store2 = [];
310744
311116
  try {
310745
- if (existsSync63(storeFile))
310746
- store2 = JSON.parse(readFileSync50(storeFile, "utf8"));
311117
+ if (existsSync64(storeFile))
311118
+ store2 = JSON.parse(readFileSync51(storeFile, "utf8"));
310747
311119
  } catch {
310748
311120
  }
310749
311121
  store2.push({
@@ -310759,26 +311131,26 @@ Rules:
310759
311131
  });
310760
311132
  if (store2.length > 100)
310761
311133
  store2 = store2.slice(-100);
310762
- mkdirSync33(metaDir, { recursive: true });
310763
- writeFileSync31(storeFile, JSON.stringify(store2, null, 2));
311134
+ mkdirSync34(metaDir, { recursive: true });
311135
+ writeFileSync32(storeFile, JSON.stringify(store2, null, 2));
310764
311136
  }
310765
311137
  }
310766
311138
  } catch {
310767
311139
  }
310768
311140
  try {
310769
- const cohereSettingsFile = join80(repoRoot, ".oa", "settings.json");
311141
+ const cohereSettingsFile = join81(repoRoot, ".oa", "settings.json");
310770
311142
  let cohereActive = false;
310771
311143
  try {
310772
- if (existsSync63(cohereSettingsFile)) {
310773
- const settings = JSON.parse(readFileSync50(cohereSettingsFile, "utf8"));
311144
+ if (existsSync64(cohereSettingsFile)) {
311145
+ const settings = JSON.parse(readFileSync51(cohereSettingsFile, "utf8"));
310774
311146
  cohereActive = settings.cohere === true;
310775
311147
  }
310776
311148
  } catch {
310777
311149
  }
310778
311150
  if (cohereActive) {
310779
- const metaFile = join80(repoRoot, ".oa", "memory", "metabolism", "store.json");
310780
- if (existsSync63(metaFile)) {
310781
- const store2 = JSON.parse(readFileSync50(metaFile, "utf8"));
311151
+ const metaFile = join81(repoRoot, ".oa", "memory", "metabolism", "store.json");
311152
+ if (existsSync64(metaFile)) {
311153
+ const store2 = JSON.parse(readFileSync51(metaFile, "utf8"));
310782
311154
  const latest = store2.filter((m2) => m2.sourceTrace === "trajectory-extraction" || m2.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
310783
311155
  if (latest && latest.scores?.confidence >= 0.6) {
310784
311156
  try {
@@ -310803,18 +311175,18 @@ Rules:
310803
311175
  }
310804
311176
  } catch (err) {
310805
311177
  try {
310806
- const ikFile = join80(repoRoot, ".oa", "identity", "self-state.json");
310807
- if (existsSync63(ikFile)) {
310808
- const ikState = JSON.parse(readFileSync50(ikFile, "utf8"));
311178
+ const ikFile = join81(repoRoot, ".oa", "identity", "self-state.json");
311179
+ if (existsSync64(ikFile)) {
311180
+ const ikState = JSON.parse(readFileSync51(ikFile, "utf8"));
310809
311181
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
310810
311182
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
310811
311183
  ikState.session_count = (ikState.session_count || 0) + 1;
310812
311184
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
310813
- writeFileSync31(ikFile, JSON.stringify(ikState, null, 2));
311185
+ writeFileSync32(ikFile, JSON.stringify(ikState, null, 2));
310814
311186
  }
310815
- const metaFile = join80(repoRoot, ".oa", "memory", "metabolism", "store.json");
310816
- if (existsSync63(metaFile)) {
310817
- const store2 = JSON.parse(readFileSync50(metaFile, "utf8"));
311187
+ const metaFile = join81(repoRoot, ".oa", "memory", "metabolism", "store.json");
311188
+ if (existsSync64(metaFile)) {
311189
+ const store2 = JSON.parse(readFileSync51(metaFile, "utf8"));
310818
311190
  const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
310819
311191
  for (const item of surfaced) {
310820
311192
  item.accessCount = (item.accessCount || 0) + 1;
@@ -310822,15 +311194,15 @@ Rules:
310822
311194
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
310823
311195
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
310824
311196
  }
310825
- writeFileSync31(metaFile, JSON.stringify(store2, null, 2));
311197
+ writeFileSync32(metaFile, JSON.stringify(store2, null, 2));
310826
311198
  }
310827
311199
  try {
310828
- const archeDir = join80(repoRoot, ".oa", "arche");
310829
- const archeFile = join80(archeDir, "variants.json");
311200
+ const archeDir = join81(repoRoot, ".oa", "arche");
311201
+ const archeFile = join81(archeDir, "variants.json");
310830
311202
  let variants = [];
310831
311203
  try {
310832
- if (existsSync63(archeFile))
310833
- variants = JSON.parse(readFileSync50(archeFile, "utf8"));
311204
+ if (existsSync64(archeFile))
311205
+ variants = JSON.parse(readFileSync51(archeFile, "utf8"));
310834
311206
  } catch {
310835
311207
  }
310836
311208
  variants.push({
@@ -310845,8 +311217,8 @@ Rules:
310845
311217
  });
310846
311218
  if (variants.length > 50)
310847
311219
  variants = variants.slice(-50);
310848
- mkdirSync33(archeDir, { recursive: true });
310849
- writeFileSync31(archeFile, JSON.stringify(variants, null, 2));
311220
+ mkdirSync34(archeDir, { recursive: true });
311221
+ writeFileSync32(archeFile, JSON.stringify(variants, null, 2));
310850
311222
  } catch {
310851
311223
  }
310852
311224
  } catch {
@@ -310924,14 +311296,14 @@ __export(run_exports, {
310924
311296
  statusCommand: () => statusCommand
310925
311297
  });
310926
311298
  import { resolve as resolve36 } from "node:path";
310927
- import { spawn as spawn24 } from "node:child_process";
310928
- import { mkdirSync as mkdirSync34, writeFileSync as writeFileSync32, readFileSync as readFileSync51, readdirSync as readdirSync25, existsSync as existsSync64 } from "node:fs";
311299
+ import { spawn as spawn25 } from "node:child_process";
311300
+ import { mkdirSync as mkdirSync35, writeFileSync as writeFileSync33, readFileSync as readFileSync52, readdirSync as readdirSync25, existsSync as existsSync65 } from "node:fs";
310929
311301
  import { randomBytes as randomBytes20 } from "node:crypto";
310930
- import { join as join81 } from "node:path";
311302
+ import { join as join82 } from "node:path";
310931
311303
  function jobsDir2(repoPath) {
310932
311304
  const root = resolve36(repoPath ?? process.cwd());
310933
- const dir = join81(root, ".oa", "jobs");
310934
- mkdirSync34(dir, { recursive: true });
311305
+ const dir = join82(root, ".oa", "jobs");
311306
+ mkdirSync35(dir, { recursive: true });
310935
311307
  return dir;
310936
311308
  }
310937
311309
  async function runCommand(opts, config) {
@@ -311034,7 +311406,7 @@ async function runBackground(task, config, opts) {
311034
311406
  const args = [task, "--json"];
311035
311407
  if (config.model)
311036
311408
  args.push("--model", config.model);
311037
- const child = spawn24(process.execPath, [oaBin, ...args], {
311409
+ const child = spawn25(process.execPath, [oaBin, ...args], {
311038
311410
  cwd: repoRoot,
311039
311411
  env: { ...process.env, OA_JOB_ID: id },
311040
311412
  stdio: ["ignore", "pipe", "pipe"],
@@ -311050,7 +311422,7 @@ async function runBackground(task, config, opts) {
311050
311422
  }
311051
311423
  });
311052
311424
  job.pid = child.pid ?? 0;
311053
- writeFileSync32(join81(dir, `${id}.json`), JSON.stringify(job, null, 2));
311425
+ writeFileSync33(join82(dir, `${id}.json`), JSON.stringify(job, null, 2));
311054
311426
  let output = "";
311055
311427
  child.stdout?.on("data", (chunk) => {
311056
311428
  output += chunk.toString();
@@ -311066,7 +311438,7 @@ async function runBackground(task, config, opts) {
311066
311438
  job.summary = result.summary;
311067
311439
  job.durationMs = result.durationMs;
311068
311440
  job.error = result.error;
311069
- writeFileSync32(join81(dir, `${id}.json`), JSON.stringify(job, null, 2));
311441
+ writeFileSync33(join82(dir, `${id}.json`), JSON.stringify(job, null, 2));
311070
311442
  } catch {
311071
311443
  }
311072
311444
  });
@@ -311082,13 +311454,13 @@ async function runBackground(task, config, opts) {
311082
311454
  }
311083
311455
  function statusCommand(jobId, repoPath) {
311084
311456
  const dir = jobsDir2(repoPath);
311085
- const file = join81(dir, `${jobId}.json`);
311086
- if (!existsSync64(file)) {
311457
+ const file = join82(dir, `${jobId}.json`);
311458
+ if (!existsSync65(file)) {
311087
311459
  console.error(`Job not found: ${jobId}`);
311088
311460
  console.log(`Available jobs: oa jobs`);
311089
311461
  process.exit(1);
311090
311462
  }
311091
- const job = JSON.parse(readFileSync51(file, "utf-8"));
311463
+ const job = JSON.parse(readFileSync52(file, "utf-8"));
311092
311464
  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`;
311093
311465
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
311094
311466
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -311111,7 +311483,7 @@ function jobsCommand(repoPath) {
311111
311483
  console.log("Jobs:");
311112
311484
  for (const file of files) {
311113
311485
  try {
311114
- const job = JSON.parse(readFileSync51(join81(dir, file), "utf-8"));
311486
+ const job = JSON.parse(readFileSync52(join82(dir, file), "utf-8"));
311115
311487
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
311116
311488
  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`;
311117
311489
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -311131,7 +311503,7 @@ import { glob as glob2 } from "glob";
311131
311503
  import ignore from "ignore";
311132
311504
  import { readFile as readFile23, stat as stat5 } from "node:fs/promises";
311133
311505
  import { createHash as createHash6 } from "node:crypto";
311134
- import { join as join82, relative as relative4, extname as extname12, basename as basename18 } from "node:path";
311506
+ import { join as join83, relative as relative4, extname as extname12, basename as basename18 } from "node:path";
311135
311507
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
311136
311508
  var init_codebase_indexer = __esm({
311137
311509
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -311175,7 +311547,7 @@ var init_codebase_indexer = __esm({
311175
311547
  const ig = ignore.default();
311176
311548
  if (this.config.respectGitignore) {
311177
311549
  try {
311178
- const gitignoreContent = await readFile23(join82(this.config.rootDir, ".gitignore"), "utf-8");
311550
+ const gitignoreContent = await readFile23(join83(this.config.rootDir, ".gitignore"), "utf-8");
311179
311551
  ig.add(gitignoreContent);
311180
311552
  } catch {
311181
311553
  }
@@ -311190,7 +311562,7 @@ var init_codebase_indexer = __esm({
311190
311562
  for (const relativePath of files) {
311191
311563
  if (ig.ignores(relativePath))
311192
311564
  continue;
311193
- const fullPath = join82(this.config.rootDir, relativePath);
311565
+ const fullPath = join83(this.config.rootDir, relativePath);
311194
311566
  try {
311195
311567
  const fileStat = await stat5(fullPath);
311196
311568
  if (fileStat.size > this.config.maxFileSize)
@@ -311236,7 +311608,7 @@ var init_codebase_indexer = __esm({
311236
311608
  if (!child) {
311237
311609
  child = {
311238
311610
  name: part,
311239
- path: join82(current.path, part),
311611
+ path: join83(current.path, part),
311240
311612
  type: "directory",
311241
311613
  children: []
311242
311614
  };
@@ -311319,13 +311691,13 @@ __export(index_repo_exports, {
311319
311691
  indexRepoCommand: () => indexRepoCommand
311320
311692
  });
311321
311693
  import { resolve as resolve37 } from "node:path";
311322
- import { existsSync as existsSync65, statSync as statSync17 } from "node:fs";
311694
+ import { existsSync as existsSync66, statSync as statSync17 } from "node:fs";
311323
311695
  import { cwd as cwd2 } from "node:process";
311324
311696
  async function indexRepoCommand(opts, _config2) {
311325
311697
  const repoRoot = resolve37(opts.repoPath ?? cwd2());
311326
311698
  printHeader("Index Repository");
311327
311699
  printInfo(`Indexing: ${repoRoot}`);
311328
- if (!existsSync65(repoRoot)) {
311700
+ if (!existsSync66(repoRoot)) {
311329
311701
  printError(`Path does not exist: ${repoRoot}`);
311330
311702
  process.exit(1);
311331
311703
  }
@@ -311577,8 +311949,8 @@ var config_exports2 = {};
311577
311949
  __export(config_exports2, {
311578
311950
  configCommand: () => configCommand
311579
311951
  });
311580
- import { join as join83, resolve as resolve38 } from "node:path";
311581
- import { homedir as homedir24 } from "node:os";
311952
+ import { join as join84, resolve as resolve38 } from "node:path";
311953
+ import { homedir as homedir25 } from "node:os";
311582
311954
  import { cwd as cwd3 } from "node:process";
311583
311955
  function redactIfSensitive(key, value2) {
311584
311956
  if (SENSITIVE_KEYS.has(key) && typeof value2 === "string" && value2.length > 0) {
@@ -311660,7 +312032,7 @@ function handleShow(opts, config) {
311660
312032
  }
311661
312033
  }
311662
312034
  printSection("Config File");
311663
- printInfo(`~/.open-agents/config.json (${join83(homedir24(), ".open-agents", "config.json")})`);
312035
+ printInfo(`~/.open-agents/config.json (${join84(homedir25(), ".open-agents", "config.json")})`);
311664
312036
  printSection("Priority Chain");
311665
312037
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
311666
312038
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -311699,7 +312071,7 @@ function handleSet(opts, _config2) {
311699
312071
  const coerced = coerceForSettings(key, value2);
311700
312072
  saveProjectSettings(repoRoot, { [key]: coerced });
311701
312073
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value2)}`);
311702
- printInfo(`Saved to ${join83(repoRoot, ".oa", "settings.json")}`);
312074
+ printInfo(`Saved to ${join84(repoRoot, ".oa", "settings.json")}`);
311703
312075
  printInfo("This override applies only when running in this workspace.");
311704
312076
  } catch (err) {
311705
312077
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -311811,11 +312183,27 @@ async function serveCommand(opts, config) {
311811
312183
  }
311812
312184
  }
311813
312185
  const ollamaUrl = config.backendUrl || "http://127.0.0.1:11434";
311814
- printHeader("Open Agents REST API");
311815
- printInfo(`Starting API server on port ${port}...`);
311816
- printInfo(`Backend: ${config.backendType} (${ollamaUrl})`);
312186
+ const isDaemon = opts.daemon || process.env["OA_DAEMON"] === "1";
312187
+ const isQuiet = opts.quiet || isDaemon;
312188
+ if (!isQuiet) {
312189
+ printHeader("Open Agents REST API");
312190
+ printInfo(`Starting API server on port ${port}...`);
312191
+ printInfo(`Backend: ${config.backendType} (${ollamaUrl})`);
312192
+ }
311817
312193
  try {
311818
- const server = startApiServer({ port, ollamaUrl });
312194
+ const server = startApiServer({ port, ollamaUrl, quiet: isQuiet });
312195
+ if (isDaemon) {
312196
+ let lastActivity = Date.now();
312197
+ const IDLE_TIMEOUT_MS = 12e4;
312198
+ server.on("request", () => {
312199
+ lastActivity = Date.now();
312200
+ });
312201
+ const idleChecker = setInterval(() => {
312202
+ if (Date.now() - lastActivity > IDLE_TIMEOUT_MS) {
312203
+ }
312204
+ }, 3e4);
312205
+ idleChecker.unref();
312206
+ }
311819
312207
  await new Promise((resolve39) => {
311820
312208
  process.on("SIGINT", () => {
311821
312209
  server.close();
@@ -311829,10 +312217,13 @@ async function serveCommand(opts, config) {
311829
312217
  } catch (err) {
311830
312218
  const msg = err instanceof Error ? err.message : String(err);
311831
312219
  if (msg.includes("EADDRINUSE")) {
311832
- printError(`Port ${port} already in use. Another OA instance may be running.`);
311833
- printInfo(`Try: oa serve --port ${port + 1}`);
312220
+ if (!isQuiet) {
312221
+ printError(`Port ${port} already in use. Another OA instance may be running.`);
312222
+ printInfo(`Try: oa serve --port ${port + 1}`);
312223
+ }
311834
312224
  } else {
311835
- printError(`API server failed: ${msg}`);
312225
+ if (!isQuiet)
312226
+ printError(`API server failed: ${msg}`);
311836
312227
  }
311837
312228
  }
311838
312229
  }
@@ -311851,8 +312242,8 @@ __export(eval_exports, {
311851
312242
  evalCommand: () => evalCommand
311852
312243
  });
311853
312244
  import { tmpdir as tmpdir10 } from "node:os";
311854
- import { mkdirSync as mkdirSync35, writeFileSync as writeFileSync33 } from "node:fs";
311855
- import { join as join84 } from "node:path";
312245
+ import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync34 } from "node:fs";
312246
+ import { join as join85 } from "node:path";
311856
312247
  async function evalCommand(opts, config) {
311857
312248
  const suiteName = opts.suite ?? "basic";
311858
312249
  const suite = SUITES[suiteName];
@@ -311977,9 +312368,9 @@ async function evalCommand(opts, config) {
311977
312368
  process.exit(failed > 0 ? 1 : 0);
311978
312369
  }
311979
312370
  function createTempEvalRepo() {
311980
- const dir = join84(tmpdir10(), `open-agents-eval-${Date.now()}`);
311981
- mkdirSync35(dir, { recursive: true });
311982
- writeFileSync33(join84(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
312371
+ const dir = join85(tmpdir10(), `open-agents-eval-${Date.now()}`);
312372
+ mkdirSync36(dir, { recursive: true });
312373
+ writeFileSync34(join85(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
311983
312374
  return dir;
311984
312375
  }
311985
312376
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -312038,8 +312429,8 @@ init_output();
312038
312429
  init_updater();
312039
312430
  import { parseArgs as nodeParseArgs2 } from "node:util";
312040
312431
  import { createRequire as createRequire6 } from "node:module";
312041
- import { fileURLToPath as fileURLToPath17 } from "node:url";
312042
- import { dirname as dirname25, join as join85 } from "node:path";
312432
+ import { fileURLToPath as fileURLToPath18 } from "node:url";
312433
+ import { dirname as dirname26, join as join86 } from "node:path";
312043
312434
 
312044
312435
  // packages/cli/dist/cli.js
312045
312436
  import { createInterface } from "node:readline";
@@ -312146,7 +312537,7 @@ init_output();
312146
312537
  function getVersion5() {
312147
312538
  try {
312148
312539
  const require3 = createRequire6(import.meta.url);
312149
- const pkgPath = join85(dirname25(fileURLToPath17(import.meta.url)), "..", "package.json");
312540
+ const pkgPath = join86(dirname26(fileURLToPath18(import.meta.url)), "..", "package.json");
312150
312541
  const pkg = require3(pkgPath);
312151
312542
  return pkg.version;
312152
312543
  } catch {
@@ -312385,7 +312776,9 @@ async function main() {
312385
312776
  await serveCommand2({
312386
312777
  port: parsed.servePort,
312387
312778
  model: parsed.model,
312388
- verbose: parsed.verbose
312779
+ verbose: parsed.verbose,
312780
+ daemon: process.env["OA_DAEMON"] === "1",
312781
+ quiet: process.argv.includes("--quiet") || process.env["OA_DAEMON"] === "1"
312389
312782
  }, config);
312390
312783
  break;
312391
312784
  }
@@ -312421,12 +312814,12 @@ function crashLog(label, err) {
312421
312814
  const logLine = `[${timestamp}] ${label}: ${msg}
312422
312815
  `;
312423
312816
  try {
312424
- const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync36 } = __require("node:fs");
312425
- const { join: join86 } = __require("node:path");
312426
- const { homedir: homedir25 } = __require("node:os");
312427
- const logDir = join86(homedir25(), ".open-agents");
312428
- mkdirSync36(logDir, { recursive: true });
312429
- appendFileSync7(join86(logDir, "crash.log"), logLine);
312817
+ const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync37 } = __require("node:fs");
312818
+ const { join: join87 } = __require("node:path");
312819
+ const { homedir: homedir26 } = __require("node:os");
312820
+ const logDir = join87(homedir26(), ".open-agents");
312821
+ mkdirSync37(logDir, { recursive: true });
312822
+ appendFileSync7(join87(logDir, "crash.log"), logLine);
312430
312823
  } catch {
312431
312824
  }
312432
312825
  try {