open-agents-ai 0.185.76 → 0.185.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +683 -402
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13782,9 +13782,9 @@ print("${sentinel}")
13782
13782
  if (!this.proc || this.proc.killed) {
13783
13783
  return { success: false, path: "" };
13784
13784
  }
13785
- const { mkdirSync: mkdirSync32, writeFileSync: writeFileSync30 } = await import("node:fs");
13785
+ const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync31 } = await import("node:fs");
13786
13786
  const sessionDir = join22(this.cwd, ".oa", "rlm");
13787
- mkdirSync32(sessionDir, { recursive: true });
13787
+ mkdirSync33(sessionDir, { recursive: true });
13788
13788
  const sessionPath = join22(sessionDir, "session.json");
13789
13789
  try {
13790
13790
  const inspectCode = `
@@ -13808,7 +13808,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13808
13808
  trajectoryCount: this.trajectory.length,
13809
13809
  subCallCount: this.subCallCount
13810
13810
  };
13811
- writeFileSync30(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13811
+ writeFileSync31(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13812
13812
  return { success: true, path: sessionPath };
13813
13813
  }
13814
13814
  } catch {
@@ -13820,11 +13820,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13820
13820
  * what was previously computed. */
13821
13821
  async loadSessionInfo() {
13822
13822
  try {
13823
- const { readFileSync: readFileSync46, existsSync: existsSync58 } = await import("node:fs");
13823
+ const { readFileSync: readFileSync47, existsSync: existsSync59 } = await import("node:fs");
13824
13824
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13825
- if (!existsSync58(sessionPath))
13825
+ if (!existsSync59(sessionPath))
13826
13826
  return null;
13827
- return JSON.parse(readFileSync46(sessionPath, "utf8"));
13827
+ return JSON.parse(readFileSync47(sessionPath, "utf8"));
13828
13828
  } catch {
13829
13829
  return null;
13830
13830
  }
@@ -13971,9 +13971,9 @@ var init_memory_metabolism = __esm({
13971
13971
  };
13972
13972
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
13973
13973
  await mkdir6(metaDir, { recursive: true });
13974
- const store = await this.loadStore(metaDir);
13975
- store.push(item);
13976
- await this.saveStore(metaDir, store);
13974
+ const store2 = await this.loadStore(metaDir);
13975
+ store2.push(item);
13976
+ await this.saveStore(metaDir, store2);
13977
13977
  if (admitted && scope !== "private" && this.deltaPublisher) {
13978
13978
  try {
13979
13979
  this.deltaPublisher({
@@ -14001,10 +14001,10 @@ var init_memory_metabolism = __esm({
14001
14001
  const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
14002
14002
  let lessons = [];
14003
14003
  try {
14004
- const { readdirSync: readdirSync24, readFileSync: readFileSync46 } = await import("node:fs");
14004
+ const { readdirSync: readdirSync24, readFileSync: readFileSync47 } = await import("node:fs");
14005
14005
  const files = readdirSync24(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
14006
14006
  for (const file of files) {
14007
- const lines = readFileSync46(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
14007
+ const lines = readFileSync47(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
14008
14008
  for (const line of lines) {
14009
14009
  try {
14010
14010
  const entry = JSON.parse(line);
@@ -14032,9 +14032,9 @@ var init_memory_metabolism = __esm({
14032
14032
  if (lessons.length > 0) {
14033
14033
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14034
14034
  await mkdir6(metaDir, { recursive: true });
14035
- const store = await this.loadStore(metaDir);
14035
+ const store2 = await this.loadStore(metaDir);
14036
14036
  for (const lesson of lessons.slice(0, 10)) {
14037
- store.push({
14037
+ store2.push({
14038
14038
  id: `lesson-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
14039
14039
  type: lesson.type === "recovery" ? "procedural" : "procedural",
14040
14040
  content: `${lesson.description}
@@ -14047,7 +14047,7 @@ Context: ${lesson.context}`,
14047
14047
  accessCount: 0
14048
14048
  });
14049
14049
  }
14050
- await this.saveStore(metaDir, store);
14050
+ await this.saveStore(metaDir, store2);
14051
14051
  }
14052
14052
  return {
14053
14053
  success: true,
@@ -14060,8 +14060,8 @@ Context: ${lesson.context}`,
14060
14060
  async listMemories(args, start) {
14061
14061
  const filterType = args.memory_type;
14062
14062
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14063
- const store = await this.loadStore(metaDir);
14064
- const filtered = filterType ? store.filter((m) => m.type === filterType) : store;
14063
+ const store2 = await this.loadStore(metaDir);
14064
+ const filtered = filterType ? store2.filter((m) => m.type === filterType) : store2;
14065
14065
  if (filtered.length === 0) {
14066
14066
  return { success: true, output: "No memories stored yet.", durationMs: performance.now() - start };
14067
14067
  }
@@ -14082,15 +14082,15 @@ ${lines.join("\n")}`,
14082
14082
  return { success: false, output: "id and memory_type required", durationMs: performance.now() - start };
14083
14083
  }
14084
14084
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14085
- const store = await this.loadStore(metaDir);
14086
- const item = store.find((m) => m.id === id);
14085
+ const store2 = await this.loadStore(metaDir);
14086
+ const item = store2.find((m) => m.id === id);
14087
14087
  if (!item) {
14088
14088
  return { success: false, output: `Memory ${id} not found`, durationMs: performance.now() - start };
14089
14089
  }
14090
14090
  const oldType = item.type;
14091
14091
  item.type = newType;
14092
14092
  item.decision = { action: "promote", reason: `Promoted from ${oldType} to ${newType}` };
14093
- await this.saveStore(metaDir, store);
14093
+ await this.saveStore(metaDir, store2);
14094
14094
  return {
14095
14095
  success: true,
14096
14096
  output: `Promoted ${id}: ${oldType} \u2192 ${newType}`,
@@ -14104,13 +14104,13 @@ ${lines.join("\n")}`,
14104
14104
  return { success: false, output: "id required", durationMs: performance.now() - start };
14105
14105
  }
14106
14106
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14107
- const store = await this.loadStore(metaDir);
14108
- const idx = store.findIndex((m) => m.id === id);
14107
+ const store2 = await this.loadStore(metaDir);
14108
+ const idx = store2.findIndex((m) => m.id === id);
14109
14109
  if (idx === -1) {
14110
14110
  return { success: false, output: `Memory ${id} not found`, durationMs: performance.now() - start };
14111
14111
  }
14112
- const removed = store.splice(idx, 1)[0];
14113
- await this.saveStore(metaDir, store);
14112
+ const removed = store2.splice(idx, 1)[0];
14113
+ await this.saveStore(metaDir, store2);
14114
14114
  return {
14115
14115
  success: true,
14116
14116
  output: `Forgotten: [${removed.id}] ${removed.content.slice(0, 60)}`,
@@ -14125,15 +14125,15 @@ ${lines.join("\n")}`,
14125
14125
  */
14126
14126
  async repairMemories(start) {
14127
14127
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14128
- const store = await this.loadStore(metaDir);
14129
- if (store.length === 0) {
14128
+ const store2 = await this.loadStore(metaDir);
14129
+ if (store2.length === 0) {
14130
14130
  return { success: true, output: "No memories to repair.", durationMs: performance.now() - start };
14131
14131
  }
14132
14132
  let repaired = 0;
14133
14133
  let quarantined = 0;
14134
14134
  let expired = 0;
14135
14135
  const issues = [];
14136
- for (const item of store) {
14136
+ for (const item of store2) {
14137
14137
  if (item.type === "working") {
14138
14138
  const ageMs = Date.now() - new Date(item.createdAt).getTime();
14139
14139
  if (ageMs > 24 * 60 * 60 * 1e3) {
@@ -14142,7 +14142,7 @@ ${lines.join("\n")}`,
14142
14142
  issues.push(`[${item.id}] Working memory expired \u2014 marked for cleanup`);
14143
14143
  }
14144
14144
  }
14145
- const duplicates = store.filter((m) => m.id !== item.id && m.content === item.content);
14145
+ const duplicates = store2.filter((m) => m.id !== item.id && m.content === item.content);
14146
14146
  if (duplicates.length > 0) {
14147
14147
  for (const dup of duplicates) {
14148
14148
  const dupScore = (dup.scores.novelty + dup.scores.utility + dup.scores.confidence + dup.scores.identityRelevance) / 4;
@@ -14156,7 +14156,7 @@ ${lines.join("\n")}`,
14156
14156
  }
14157
14157
  }
14158
14158
  if (item.type === "procedural" || item.type === "semantic") {
14159
- const conflicts = store.filter((m) => m.id !== item.id && m.type === item.type && m.decision.action !== "quarantine" && this.detectContradiction(item.content, m.content));
14159
+ const conflicts = store2.filter((m) => m.id !== item.id && m.type === item.type && m.decision.action !== "quarantine" && this.detectContradiction(item.content, m.content));
14160
14160
  if (conflicts.length > 0) {
14161
14161
  for (const conflict of conflicts) {
14162
14162
  if (new Date(conflict.createdAt) < new Date(item.createdAt)) {
@@ -14176,12 +14176,12 @@ ${lines.join("\n")}`,
14176
14176
  issues.push(`[${item.id}] Low confidence (${item.scores.confidence.toFixed(2)}) \u2014 quarantined`);
14177
14177
  }
14178
14178
  }
14179
- const cleanedStore = store.filter((m) => !(m.type === "working" && m.decision.action === "forget"));
14179
+ const cleanedStore = store2.filter((m) => !(m.type === "working" && m.decision.action === "forget"));
14180
14180
  await this.saveStore(metaDir, cleanedStore);
14181
14181
  return {
14182
14182
  success: true,
14183
14183
  output: `Memory repair complete:
14184
- Scanned: ${store.length} memories
14184
+ Scanned: ${store2.length} memories
14185
14185
  Repaired contradictions: ${repaired}
14186
14186
  Quarantined (duplicates/low-confidence): ${quarantined}
14187
14187
  Expired working memories removed: ${expired}
@@ -14293,14 +14293,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14293
14293
  // Memories below decay threshold get quarantined.
14294
14294
  async decayMemories(start) {
14295
14295
  const dir = join23(this.cwd, ".oa", "memory", "metabolism");
14296
- const store = await this.loadStore(dir);
14297
- if (store.length === 0)
14296
+ const store2 = await this.loadStore(dir);
14297
+ if (store2.length === 0)
14298
14298
  return { success: true, output: "No memories to decay", durationMs: performance.now() - start };
14299
14299
  const now = Date.now();
14300
14300
  const DECAY_RATE = 1e-3;
14301
14301
  const QUARANTINE_THRESHOLD = 0.15;
14302
14302
  let decayed = 0, quarantined = 0;
14303
- for (const item of store) {
14303
+ for (const item of store2) {
14304
14304
  if (item.type === "quarantine")
14305
14305
  continue;
14306
14306
  const ageHours = (now - new Date(item.lastAccessedAt).getTime()) / (1e3 * 60 * 60);
@@ -14317,7 +14317,7 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14317
14317
  quarantined++;
14318
14318
  }
14319
14319
  }
14320
- await this.saveStore(dir, store);
14320
+ await this.saveStore(dir, store2);
14321
14321
  return {
14322
14322
  success: true,
14323
14323
  output: `Decay sweep: ${decayed} memories updated, ${quarantined} quarantined (threshold: ${QUARANTINE_THRESHOLD})`,
@@ -14332,11 +14332,11 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14332
14332
  // Any → procedural: if content matches action/strategy patterns
14333
14333
  async autoLifecycle(start) {
14334
14334
  const dir = join23(this.cwd, ".oa", "memory", "metabolism");
14335
- const store = await this.loadStore(dir);
14336
- if (store.length === 0)
14335
+ const store2 = await this.loadStore(dir);
14336
+ if (store2.length === 0)
14337
14337
  return { success: true, output: "No memories to process", durationMs: performance.now() - start };
14338
14338
  let promoted = 0;
14339
- for (const item of store) {
14339
+ for (const item of store2) {
14340
14340
  if (item.type === "quarantine")
14341
14341
  continue;
14342
14342
  if (item.type === "working" && item.accessCount >= 3) {
@@ -14358,18 +14358,18 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14358
14358
  }
14359
14359
  }
14360
14360
  const decayResult = await this.decayMemories(start);
14361
- await this.saveStore(dir, store);
14361
+ await this.saveStore(dir, store2);
14362
14362
  try {
14363
14363
  const { IdentityKernelTool: IdentityKernelTool2 } = await Promise.resolve().then(() => (init_identity_kernel(), identity_kernel_exports));
14364
14364
  const ik = new IdentityKernelTool2(this.cwd);
14365
14365
  const typeCounts = {};
14366
- for (const item of store) {
14366
+ for (const item of store2) {
14367
14367
  typeCounts[item.type] = (typeCounts[item.type] || 0) + 1;
14368
14368
  }
14369
14369
  await ik.execute({
14370
14370
  op: "observe",
14371
- event: `Memory lifecycle: ${store.length} total, ${promoted} promoted. Types: ${JSON.stringify(typeCounts)}`,
14372
- context: JSON.stringify({ total: store.length, promoted, typeCounts })
14371
+ event: `Memory lifecycle: ${store2.length} total, ${promoted} promoted. Types: ${JSON.stringify(typeCounts)}`,
14372
+ context: JSON.stringify({ total: store2.length, promoted, typeCounts })
14373
14373
  });
14374
14374
  } catch {
14375
14375
  }
@@ -14388,18 +14388,18 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14388
14388
  * Optionally filter by task type for phase-aware context (FSM paper insight).
14389
14389
  */
14390
14390
  getTopMemoriesSync(k = 5, taskType) {
14391
- const { readFileSync: readFileSync46, existsSync: existsSync58 } = __require("node:fs");
14391
+ const { readFileSync: readFileSync47, existsSync: existsSync59 } = __require("node:fs");
14392
14392
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14393
14393
  const storeFile = join23(metaDir, "store.json");
14394
- if (!existsSync58(storeFile))
14394
+ if (!existsSync59(storeFile))
14395
14395
  return "";
14396
- let store = [];
14396
+ let store2 = [];
14397
14397
  try {
14398
- store = JSON.parse(readFileSync46(storeFile, "utf8"));
14398
+ store2 = JSON.parse(readFileSync47(storeFile, "utf8"));
14399
14399
  } catch {
14400
14400
  return "";
14401
14401
  }
14402
- let items = store.filter((m) => m.type !== "quarantine" && m.scores.confidence > 0.15);
14402
+ let items = store2.filter((m) => m.type !== "quarantine" && m.scores.confidence > 0.15);
14403
14403
  if (taskType) {
14404
14404
  const typeMatch = items.filter((m) => m.content.toLowerCase().includes(taskType.toLowerCase()) || m.sourceTrace.toLowerCase().includes(taskType.toLowerCase()));
14405
14405
  if (typeMatch.length >= 2)
@@ -14417,14 +14417,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14417
14417
  /** Update memory scores based on task outcome. Called after task completion.
14418
14418
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
14419
14419
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
14420
- const { readFileSync: readFileSync46, writeFileSync: writeFileSync30, existsSync: existsSync58, mkdirSync: mkdirSync32 } = __require("node:fs");
14420
+ const { readFileSync: readFileSync47, writeFileSync: writeFileSync31, existsSync: existsSync59, mkdirSync: mkdirSync33 } = __require("node:fs");
14421
14421
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14422
14422
  const storeFile = join23(metaDir, "store.json");
14423
- if (!existsSync58(storeFile))
14423
+ if (!existsSync59(storeFile))
14424
14424
  return;
14425
- let store = [];
14425
+ let store2 = [];
14426
14426
  try {
14427
- store = JSON.parse(readFileSync46(storeFile, "utf8"));
14427
+ store2 = JSON.parse(readFileSync47(storeFile, "utf8"));
14428
14428
  } catch {
14429
14429
  return;
14430
14430
  }
@@ -14433,7 +14433,7 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14433
14433
  return;
14434
14434
  const surfacedIds = new Set(idMatches.map((m) => m.slice(1, -1)));
14435
14435
  let updated = false;
14436
- for (const item of store) {
14436
+ for (const item of store2) {
14437
14437
  if (!surfacedIds.has(item.id))
14438
14438
  continue;
14439
14439
  item.accessCount++;
@@ -14448,8 +14448,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14448
14448
  updated = true;
14449
14449
  }
14450
14450
  if (updated) {
14451
- mkdirSync32(metaDir, { recursive: true });
14452
- writeFileSync30(storeFile, JSON.stringify(store, null, 2));
14451
+ mkdirSync33(metaDir, { recursive: true });
14452
+ writeFileSync31(storeFile, JSON.stringify(store2, null, 2));
14453
14453
  }
14454
14454
  }
14455
14455
  // ── Storage ──────────────────────────────────────────────────────────
@@ -14871,13 +14871,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14871
14871
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
14872
14872
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
14873
14873
  getRelevantStrategiesSync(k = 3, taskType) {
14874
- const { readFileSync: readFileSync46, existsSync: existsSync58 } = __require("node:fs");
14874
+ const { readFileSync: readFileSync47, existsSync: existsSync59 } = __require("node:fs");
14875
14875
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14876
- if (!existsSync58(archiveFile))
14876
+ if (!existsSync59(archiveFile))
14877
14877
  return "";
14878
14878
  let variants = [];
14879
14879
  try {
14880
- variants = JSON.parse(readFileSync46(archiveFile, "utf8"));
14880
+ variants = JSON.parse(readFileSync47(archiveFile, "utf8"));
14881
14881
  } catch {
14882
14882
  return "";
14883
14883
  }
@@ -14895,13 +14895,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14895
14895
  }
14896
14896
  /** Archive a strategy variant synchronously (for task completion path) */
14897
14897
  archiveVariantSync(strategy, outcome, tags = []) {
14898
- const { readFileSync: readFileSync46, writeFileSync: writeFileSync30, existsSync: existsSync58, mkdirSync: mkdirSync32 } = __require("node:fs");
14898
+ const { readFileSync: readFileSync47, writeFileSync: writeFileSync31, existsSync: existsSync59, mkdirSync: mkdirSync33 } = __require("node:fs");
14899
14899
  const dir = join25(this.cwd, ".oa", "arche");
14900
14900
  const archiveFile = join25(dir, "variants.json");
14901
14901
  let variants = [];
14902
14902
  try {
14903
- if (existsSync58(archiveFile))
14904
- variants = JSON.parse(readFileSync46(archiveFile, "utf8"));
14903
+ if (existsSync59(archiveFile))
14904
+ variants = JSON.parse(readFileSync47(archiveFile, "utf8"));
14905
14905
  } catch {
14906
14906
  }
14907
14907
  variants.push({
@@ -14916,8 +14916,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14916
14916
  });
14917
14917
  if (variants.length > 50)
14918
14918
  variants = variants.slice(-50);
14919
- mkdirSync32(dir, { recursive: true });
14920
- writeFileSync30(archiveFile, JSON.stringify(variants, null, 2));
14919
+ mkdirSync33(dir, { recursive: true });
14920
+ writeFileSync31(archiveFile, JSON.stringify(variants, null, 2));
14921
14921
  }
14922
14922
  async saveArchive(variants) {
14923
14923
  const dir = join25(this.cwd, ".oa", "arche");
@@ -18168,12 +18168,12 @@ async function loadStore(workingDir) {
18168
18168
  return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18169
18169
  }
18170
18170
  }
18171
- async function saveStore(workingDir, store) {
18171
+ async function saveStore(workingDir, store2) {
18172
18172
  const dir = resolve23(workingDir, ".oa", "scheduled");
18173
18173
  await mkdir11(dir, { recursive: true });
18174
18174
  await mkdir11(join34(dir, "logs"), { recursive: true });
18175
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18176
- await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
18175
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18176
+ await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store2, null, 2), "utf-8");
18177
18177
  }
18178
18178
  function globalStoreDir() {
18179
18179
  return join34(homedir9(), ".open-agents", "scheduled");
@@ -18186,12 +18186,12 @@ async function loadGlobalStore() {
18186
18186
  return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18187
18187
  }
18188
18188
  }
18189
- async function saveGlobalStore(store) {
18189
+ async function saveGlobalStore(store2) {
18190
18190
  const dir = globalStoreDir();
18191
18191
  await mkdir11(dir, { recursive: true });
18192
18192
  await mkdir11(join34(dir, "logs"), { recursive: true });
18193
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18194
- await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
18193
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18194
+ await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store2, null, 2), "utf-8");
18195
18195
  }
18196
18196
  async function loadAllStores(workingDir) {
18197
18197
  const [local, global] = await Promise.all([
@@ -18332,13 +18332,13 @@ var init_scheduler = __esm({
18332
18332
  projectDir: resolve23(this.workingDir)
18333
18333
  };
18334
18334
  if (scope === "global") {
18335
- const store = await loadGlobalStore();
18336
- store.tasks.push(newTask);
18337
- await saveGlobalStore(store);
18335
+ const store2 = await loadGlobalStore();
18336
+ store2.tasks.push(newTask);
18337
+ await saveGlobalStore(store2);
18338
18338
  } else {
18339
- const store = await loadStore(this.workingDir);
18340
- store.tasks.push(newTask);
18341
- await saveStore(this.workingDir, store);
18339
+ const store2 = await loadStore(this.workingDir);
18340
+ store2.tasks.push(newTask);
18341
+ await saveStore(this.workingDir, store2);
18342
18342
  }
18343
18343
  installCronJob(newTask, this.workingDir);
18344
18344
  return {
@@ -18418,12 +18418,12 @@ var init_scheduler = __esm({
18418
18418
  const id = String(args["id"] ?? "");
18419
18419
  if (!id)
18420
18420
  return { success: false, output: "", error: "id is required for cancel action", durationMs: performance.now() - start };
18421
- const store = await loadStore(this.workingDir);
18422
- const idx = store.tasks.findIndex((t) => t.id === id);
18421
+ const store2 = await loadStore(this.workingDir);
18422
+ const idx = store2.tasks.findIndex((t) => t.id === id);
18423
18423
  if (idx === -1)
18424
18424
  return { success: false, output: "", error: `No task found with ID '${id}'`, durationMs: performance.now() - start };
18425
- const removed = store.tasks.splice(idx, 1)[0];
18426
- await saveStore(this.workingDir, store);
18425
+ const removed = store2.tasks.splice(idx, 1)[0];
18426
+ await saveStore(this.workingDir, store2);
18427
18427
  removeCronJob(id);
18428
18428
  return {
18429
18429
  success: true,
@@ -18435,12 +18435,12 @@ var init_scheduler = __esm({
18435
18435
  const id = String(args["id"] ?? "");
18436
18436
  if (!id)
18437
18437
  return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
18438
- const store = await loadStore(this.workingDir);
18439
- const task = store.tasks.find((t) => t.id === id);
18438
+ const store2 = await loadStore(this.workingDir);
18439
+ const task = store2.tasks.find((t) => t.id === id);
18440
18440
  if (!task)
18441
18441
  return { success: false, output: "", error: `No task found with ID '${id}'`, durationMs: performance.now() - start };
18442
18442
  task.enabled = enable;
18443
- await saveStore(this.workingDir, store);
18443
+ await saveStore(this.workingDir, store2);
18444
18444
  if (enable) {
18445
18445
  installCronJob(task, this.workingDir);
18446
18446
  } else {
@@ -18535,15 +18535,15 @@ async function loadReminderStore(workingDir) {
18535
18535
  return { reminders: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18536
18536
  }
18537
18537
  }
18538
- async function saveReminderStore(workingDir, store) {
18538
+ async function saveReminderStore(workingDir, store2) {
18539
18539
  const storePath = await getStorePath(workingDir);
18540
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18541
- await writeFile16(storePath, JSON.stringify(store, null, 2), "utf-8");
18540
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18541
+ await writeFile16(storePath, JSON.stringify(store2, null, 2), "utf-8");
18542
18542
  }
18543
18543
  async function getDueReminders(workingDir) {
18544
- const store = await loadReminderStore(workingDir);
18544
+ const store2 = await loadReminderStore(workingDir);
18545
18545
  const now = /* @__PURE__ */ new Date();
18546
- return store.reminders.filter((r) => {
18546
+ return store2.reminders.filter((r) => {
18547
18547
  if (r.status !== "pending")
18548
18548
  return false;
18549
18549
  if (!r.dueAt)
@@ -18552,15 +18552,15 @@ async function getDueReminders(workingDir) {
18552
18552
  });
18553
18553
  }
18554
18554
  async function markRemindersSeen(workingDir, ids) {
18555
- const store = await loadReminderStore(workingDir);
18555
+ const store2 = await loadReminderStore(workingDir);
18556
18556
  const idSet = new Set(ids);
18557
- for (const r of store.reminders) {
18557
+ for (const r of store2.reminders) {
18558
18558
  if (idSet.has(r.id) && r.status === "pending") {
18559
18559
  r.status = "seen";
18560
18560
  r.seenAt = (/* @__PURE__ */ new Date()).toISOString();
18561
18561
  }
18562
18562
  }
18563
- await saveReminderStore(workingDir, store);
18563
+ await saveReminderStore(workingDir, store2);
18564
18564
  }
18565
18565
  var STORE_FILE, ReminderTool;
18566
18566
  var init_reminder = __esm({
@@ -18683,9 +18683,9 @@ var init_reminder = __esm({
18683
18683
  context,
18684
18684
  source: "agent"
18685
18685
  };
18686
- const store = await loadReminderStore(this.workingDir);
18687
- store.reminders.push(entry);
18688
- await saveReminderStore(this.workingDir, store);
18686
+ const store2 = await loadReminderStore(this.workingDir);
18687
+ store2.reminders.push(entry);
18688
+ await saveReminderStore(this.workingDir, store2);
18689
18689
  return {
18690
18690
  success: true,
18691
18691
  output: [
@@ -18703,9 +18703,9 @@ var init_reminder = __esm({
18703
18703
  };
18704
18704
  }
18705
18705
  async listReminders(args, start) {
18706
- const store = await loadReminderStore(this.workingDir);
18706
+ const store2 = await loadReminderStore(this.workingDir);
18707
18707
  const filter = String(args["filter"] ?? "pending");
18708
- let filtered = store.reminders;
18708
+ let filtered = store2.reminders;
18709
18709
  if (filter === "pending")
18710
18710
  filtered = filtered.filter((r) => r.status === "pending" || r.status === "seen");
18711
18711
  else if (filter !== "all")
@@ -18744,12 +18744,12 @@ var init_reminder = __esm({
18744
18744
  const id = String(args["id"] ?? "");
18745
18745
  if (!id)
18746
18746
  return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
18747
- const store = await loadReminderStore(this.workingDir);
18748
- const reminder = store.reminders.find((r) => r.id === id);
18747
+ const store2 = await loadReminderStore(this.workingDir);
18748
+ const reminder = store2.reminders.find((r) => r.id === id);
18749
18749
  if (!reminder)
18750
18750
  return { success: false, output: "", error: `No reminder found with ID '${id}'`, durationMs: performance.now() - start };
18751
18751
  reminder.status = status;
18752
- await saveReminderStore(this.workingDir, store);
18752
+ await saveReminderStore(this.workingDir, store2);
18753
18753
  return {
18754
18754
  success: true,
18755
18755
  output: `Reminder '${id}' marked as ${status}: ${reminder.message.slice(0, 80)}`,
@@ -18764,15 +18764,15 @@ var init_reminder = __esm({
18764
18764
  const parsed = parseDueTime(due);
18765
18765
  if (!parsed)
18766
18766
  return { success: false, output: "", error: `Cannot parse due time '${due}'`, durationMs: performance.now() - start };
18767
- const store = await loadReminderStore(this.workingDir);
18768
- const reminder = store.reminders.find((r) => r.id === id);
18767
+ const store2 = await loadReminderStore(this.workingDir);
18768
+ const reminder = store2.reminders.find((r) => r.id === id);
18769
18769
  if (!reminder)
18770
18770
  return { success: false, output: "", error: `No reminder found with ID '${id}'`, durationMs: performance.now() - start };
18771
18771
  reminder.status = "pending";
18772
18772
  reminder.dueAt = parsed.isoDate;
18773
18773
  reminder.dueDescription = parsed.description;
18774
18774
  reminder.seenAt = void 0;
18775
- await saveReminderStore(this.workingDir, store);
18775
+ await saveReminderStore(this.workingDir, store2);
18776
18776
  return {
18777
18777
  success: true,
18778
18778
  output: `Reminder '${id}' snoozed until ${parsed.description}: ${reminder.message.slice(0, 80)}`,
@@ -18796,25 +18796,25 @@ async function loadAttentionStore(workingDir) {
18796
18796
  return { items: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18797
18797
  }
18798
18798
  }
18799
- async function saveAttentionStore(workingDir, store) {
18799
+ async function saveAttentionStore(workingDir, store2) {
18800
18800
  const dir = resolve25(workingDir, ".oa", "scheduled");
18801
18801
  await mkdir13(dir, { recursive: true });
18802
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18803
- await writeFile17(join36(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
18802
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18803
+ await writeFile17(join36(dir, "attention.json"), JSON.stringify(store2, null, 2), "utf-8");
18804
18804
  }
18805
18805
  async function getActiveAttentionItems(workingDir) {
18806
- const store = await loadAttentionStore(workingDir);
18806
+ const store2 = await loadAttentionStore(workingDir);
18807
18807
  const now = /* @__PURE__ */ new Date();
18808
18808
  let changed = false;
18809
- for (const item of store.items) {
18809
+ for (const item of store2.items) {
18810
18810
  if (item.status === "active" && item.expiresAt && new Date(item.expiresAt) <= now) {
18811
18811
  item.status = "expired";
18812
18812
  changed = true;
18813
18813
  }
18814
18814
  }
18815
18815
  if (changed)
18816
- await saveAttentionStore(workingDir, store);
18817
- return store.items.filter((i) => i.status === "active");
18816
+ await saveAttentionStore(workingDir, store2);
18817
+ return store2.items.filter((i) => i.status === "active");
18818
18818
  }
18819
18819
  var AgendaTool;
18820
18820
  var init_agenda = __esm({
@@ -19002,9 +19002,9 @@ ${sections.join("\n")}`,
19002
19002
  status: "active",
19003
19003
  notes: notes2
19004
19004
  };
19005
- const store = await loadAttentionStore(this.workingDir);
19006
- store.items.push(item);
19007
- await saveAttentionStore(this.workingDir, store);
19005
+ const store2 = await loadAttentionStore(this.workingDir);
19006
+ store2.items.push(item);
19007
+ await saveAttentionStore(this.workingDir, store2);
19008
19008
  return {
19009
19009
  success: true,
19010
19010
  output: [
@@ -19025,13 +19025,13 @@ ${sections.join("\n")}`,
19025
19025
  const id = String(args["id"] ?? "");
19026
19026
  if (!id)
19027
19027
  return { success: false, output: "", error: "id is required for resolve", durationMs: performance.now() - start };
19028
- const store = await loadAttentionStore(this.workingDir);
19029
- const item = store.items.find((i) => i.id === id);
19028
+ const store2 = await loadAttentionStore(this.workingDir);
19029
+ const item = store2.items.find((i) => i.id === id);
19030
19030
  if (!item)
19031
19031
  return { success: false, output: "", error: `No attention item found with ID '${id}'`, durationMs: performance.now() - start };
19032
19032
  item.status = "resolved";
19033
19033
  item.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
19034
- await saveAttentionStore(this.workingDir, store);
19034
+ await saveAttentionStore(this.workingDir, store2);
19035
19035
  return {
19036
19036
  success: true,
19037
19037
  output: `Attention item '${id}' resolved: ${item.title}`,
@@ -19097,8 +19097,8 @@ ${sections.join("\n")}`,
19097
19097
  try {
19098
19098
  const storePath = resolve25(this.workingDir, ".oa", "scheduled", "tasks.json");
19099
19099
  const raw = await readFile17(storePath, "utf-8");
19100
- const store = JSON.parse(raw);
19101
- return store.tasks ?? [];
19100
+ const store2 = JSON.parse(raw);
19101
+ return store2.tasks ?? [];
19102
19102
  } catch {
19103
19103
  return [];
19104
19104
  }
@@ -19816,12 +19816,12 @@ async function loadStore2(workingDir) {
19816
19816
  return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
19817
19817
  }
19818
19818
  }
19819
- async function saveStore2(workingDir, store) {
19819
+ async function saveStore2(workingDir, store2) {
19820
19820
  const dir = resolve27(workingDir, ".oa", "cron-agents");
19821
19821
  await mkdir14(dir, { recursive: true });
19822
19822
  await mkdir14(join39(dir, "logs"), { recursive: true });
19823
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
19824
- await writeFile18(join39(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
19823
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
19824
+ await writeFile18(join39(dir, "store.json"), JSON.stringify(store2, null, 2), "utf-8");
19825
19825
  }
19826
19826
  function globalCronDir() {
19827
19827
  return join39(homedir10(), ".open-agents", "cron-agents");
@@ -19834,12 +19834,12 @@ async function loadGlobalCronStore() {
19834
19834
  return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
19835
19835
  }
19836
19836
  }
19837
- async function saveGlobalCronStore(store) {
19837
+ async function saveGlobalCronStore(store2) {
19838
19838
  const dir = globalCronDir();
19839
19839
  await mkdir14(dir, { recursive: true });
19840
19840
  await mkdir14(join39(dir, "logs"), { recursive: true });
19841
- store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
19842
- await writeFile18(join39(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
19841
+ store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
19842
+ await writeFile18(join39(dir, "store.json"), JSON.stringify(store2, null, 2), "utf-8");
19843
19843
  }
19844
19844
  async function loadAllCronStores(workingDir) {
19845
19845
  const [local, global] = await Promise.all([
@@ -20008,13 +20008,13 @@ var init_cron_agent = __esm({
20008
20008
  projectDir: resolve27(this.workingDir)
20009
20009
  };
20010
20010
  if (scope === "global") {
20011
- const store = await loadGlobalCronStore();
20012
- store.jobs.push(job);
20013
- await saveGlobalCronStore(store);
20011
+ const store2 = await loadGlobalCronStore();
20012
+ store2.jobs.push(job);
20013
+ await saveGlobalCronStore(store2);
20014
20014
  } else {
20015
- const store = await loadStore2(this.workingDir);
20016
- store.jobs.push(job);
20017
- await saveStore2(this.workingDir, store);
20015
+ const store2 = await loadStore2(this.workingDir);
20016
+ store2.jobs.push(job);
20017
+ await saveStore2(this.workingDir, store2);
20018
20018
  }
20019
20019
  installCronAgentJob(job, this.workingDir);
20020
20020
  return {
@@ -20089,8 +20089,8 @@ var init_cron_agent = __esm({
20089
20089
  const id = String(args["id"] ?? "");
20090
20090
  if (!id)
20091
20091
  return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
20092
- const store = await loadStore2(this.workingDir);
20093
- const job = store.jobs.find((j) => j.id === id);
20092
+ const store2 = await loadStore2(this.workingDir);
20093
+ const job = store2.jobs.find((j) => j.id === id);
20094
20094
  if (!job)
20095
20095
  return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
20096
20096
  const lines = [
@@ -20124,12 +20124,12 @@ var init_cron_agent = __esm({
20124
20124
  const id = String(args["id"] ?? "");
20125
20125
  if (!id)
20126
20126
  return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
20127
- const store = await loadStore2(this.workingDir);
20128
- const idx = store.jobs.findIndex((j) => j.id === id);
20127
+ const store2 = await loadStore2(this.workingDir);
20128
+ const idx = store2.jobs.findIndex((j) => j.id === id);
20129
20129
  if (idx === -1)
20130
20130
  return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
20131
- const removed = store.jobs.splice(idx, 1)[0];
20132
- await saveStore2(this.workingDir, store);
20131
+ const removed = store2.jobs.splice(idx, 1)[0];
20132
+ await saveStore2(this.workingDir, store2);
20133
20133
  removeCronAgentJob(id);
20134
20134
  return {
20135
20135
  success: true,
@@ -20155,8 +20155,8 @@ ${truncated}`, durationMs: performance.now() - start };
20155
20155
  const id = String(args["id"] ?? "");
20156
20156
  if (!id)
20157
20157
  return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
20158
- const store = await loadStore2(this.workingDir);
20159
- const job = store.jobs.find((j) => j.id === id);
20158
+ const store2 = await loadStore2(this.workingDir);
20159
+ const job = store2.jobs.find((j) => j.id === id);
20160
20160
  if (!job)
20161
20161
  return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
20162
20162
  const lines = [
@@ -20181,7 +20181,7 @@ ${truncated}`, durationMs: performance.now() - start };
20181
20181
  lines.push(` cron_agent(action='cancel', id='${id}')`);
20182
20182
  job.status = "completed";
20183
20183
  removeCronAgentJob(id);
20184
- await saveStore2(this.workingDir, store);
20184
+ await saveStore2(this.workingDir, store2);
20185
20185
  lines.push(" Status automatically set to COMPLETED.");
20186
20186
  } catch (err) {
20187
20187
  const errMsg = err instanceof Error ? err.stderr?.toString() || err.message : String(err);
@@ -27422,10 +27422,10 @@ ${marker}` : marker);
27422
27422
  if (!this._workingDirectory)
27423
27423
  return;
27424
27424
  try {
27425
- const { mkdirSync: mkdirSync32, writeFileSync: writeFileSync30 } = __require("node:fs");
27426
- const { join: join78 } = __require("node:path");
27427
- const sessionDir = join78(this._workingDirectory, ".oa", "session", this._sessionId);
27428
- mkdirSync32(sessionDir, { recursive: true });
27425
+ const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync31 } = __require("node:fs");
27426
+ const { join: join79 } = __require("node:path");
27427
+ const sessionDir = join79(this._workingDirectory, ".oa", "session", this._sessionId);
27428
+ mkdirSync33(sessionDir, { recursive: true });
27429
27429
  const checkpoint = {
27430
27430
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
27431
27431
  sessionId: this._sessionId,
@@ -27437,7 +27437,7 @@ ${marker}` : marker);
27437
27437
  memexEntryCount: this._memexArchive.size,
27438
27438
  fileRegistrySize: this._fileRegistry.size
27439
27439
  };
27440
- writeFileSync30(join78(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27440
+ writeFileSync31(join79(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27441
27441
  } catch {
27442
27442
  }
27443
27443
  }
@@ -28575,17 +28575,17 @@ ${transcript}`
28575
28575
  let resizedBase64 = null;
28576
28576
  try {
28577
28577
  const { execSync: execSync36 } = await import("node:child_process");
28578
- const { writeFileSync: writeFileSync30, readFileSync: readFileSync46, unlinkSync: unlinkSync13 } = await import("node:fs");
28579
- const { join: join78 } = await import("node:path");
28578
+ const { writeFileSync: writeFileSync31, readFileSync: readFileSync47, unlinkSync: unlinkSync13 } = await import("node:fs");
28579
+ const { join: join79 } = await import("node:path");
28580
28580
  const { tmpdir: tmpdir11 } = await import("node:os");
28581
- const tmpIn = join78(tmpdir11(), `oa_img_in_${Date.now()}.png`);
28582
- const tmpOut = join78(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
28583
- writeFileSync30(tmpIn, buffer);
28581
+ const tmpIn = join79(tmpdir11(), `oa_img_in_${Date.now()}.png`);
28582
+ const tmpOut = join79(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
28583
+ writeFileSync31(tmpIn, buffer);
28584
28584
  const pyBin = process.platform === "win32" ? "python" : "python3";
28585
28585
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
28586
28586
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
28587
28587
  execSync36(`${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" });
28588
- const resizedBuf = readFileSync46(tmpOut);
28588
+ const resizedBuf = readFileSync47(tmpOut);
28589
28589
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
28590
28590
  try {
28591
28591
  unlinkSync13(tmpIn);
@@ -39557,26 +39557,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
39557
39557
  async function fetchPeerModels(peerId, authKey) {
39558
39558
  try {
39559
39559
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
39560
- const { existsSync: existsSync58, readFileSync: readFileSync46 } = await import("node:fs");
39561
- const { join: join78 } = await import("node:path");
39560
+ const { existsSync: existsSync59, readFileSync: readFileSync47 } = await import("node:fs");
39561
+ const { join: join79 } = await import("node:path");
39562
39562
  const cwd4 = process.cwd();
39563
39563
  const nexusTool = new NexusTool2(cwd4);
39564
39564
  const nexusDir = nexusTool.getNexusDir();
39565
39565
  let isLocalPeer = false;
39566
39566
  try {
39567
- const statusPath = join78(nexusDir, "status.json");
39568
- if (existsSync58(statusPath)) {
39569
- const status = JSON.parse(readFileSync46(statusPath, "utf8"));
39567
+ const statusPath = join79(nexusDir, "status.json");
39568
+ if (existsSync59(statusPath)) {
39569
+ const status = JSON.parse(readFileSync47(statusPath, "utf8"));
39570
39570
  if (status.peerId === peerId)
39571
39571
  isLocalPeer = true;
39572
39572
  }
39573
39573
  } catch {
39574
39574
  }
39575
39575
  if (isLocalPeer) {
39576
- const pricingPath = join78(nexusDir, "pricing.json");
39577
- if (existsSync58(pricingPath)) {
39576
+ const pricingPath = join79(nexusDir, "pricing.json");
39577
+ if (existsSync59(pricingPath)) {
39578
39578
  try {
39579
- const pricing = JSON.parse(readFileSync46(pricingPath, "utf8"));
39579
+ const pricing = JSON.parse(readFileSync47(pricingPath, "utf8"));
39580
39580
  const localModels = (pricing.models || []).map((m) => ({
39581
39581
  name: m.model || "unknown",
39582
39582
  size: m.parameterSize || "",
@@ -39590,10 +39590,10 @@ async function fetchPeerModels(peerId, authKey) {
39590
39590
  }
39591
39591
  }
39592
39592
  }
39593
- const cachePath = join78(nexusDir, "peer-models-cache.json");
39594
- if (existsSync58(cachePath)) {
39593
+ const cachePath = join79(nexusDir, "peer-models-cache.json");
39594
+ if (existsSync59(cachePath)) {
39595
39595
  try {
39596
- const cache4 = JSON.parse(readFileSync46(cachePath, "utf8"));
39596
+ const cache4 = JSON.parse(readFileSync47(cachePath, "utf8"));
39597
39597
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
39598
39598
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
39599
39599
  if (age < 5 * 60 * 1e3) {
@@ -39708,10 +39708,10 @@ async function fetchPeerModels(peerId, authKey) {
39708
39708
  } catch {
39709
39709
  }
39710
39710
  if (isLocalPeer) {
39711
- const pricingPath = join78(nexusDir, "pricing.json");
39712
- if (existsSync58(pricingPath)) {
39711
+ const pricingPath = join79(nexusDir, "pricing.json");
39712
+ if (existsSync59(pricingPath)) {
39713
39713
  try {
39714
- const pricing = JSON.parse(readFileSync46(pricingPath, "utf8"));
39714
+ const pricing = JSON.parse(readFileSync47(pricingPath, "utf8"));
39715
39715
  return (pricing.models || []).map((m) => ({
39716
39716
  name: m.model || "unknown",
39717
39717
  size: m.parameterSize || "",
@@ -49671,8 +49671,8 @@ async function handleSlashCommand(input, ctx) {
49671
49671
  try {
49672
49672
  const metaFile = join59(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
49673
49673
  if (existsSync43(metaFile)) {
49674
- const store = JSON.parse(readFileSync32(metaFile, "utf8"));
49675
- const active = store.filter((m) => m.type !== "quarantine");
49674
+ const store2 = JSON.parse(readFileSync32(metaFile, "utf8"));
49675
+ const active = store2.filter((m) => m.type !== "quarantine");
49676
49676
  const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
49677
49677
  const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
49678
49678
  const optimizations = active.filter((m) => m.content?.startsWith("[optimization]")).length;
@@ -52121,12 +52121,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
52121
52121
  continue;
52122
52122
  }
52123
52123
  const { basename: basename18, join: pathJoin } = await import("node:path");
52124
- const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync32, existsSync: exists } = await import("node:fs");
52124
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync33, existsSync: exists } = await import("node:fs");
52125
52125
  const { homedir: homedir21 } = await import("node:os");
52126
52126
  const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
52127
52127
  const destDir = pathJoin(homedir21(), ".open-agents", "voice", "models", modelName);
52128
52128
  if (!exists(destDir))
52129
- mkdirSync32(destDir, { recursive: true });
52129
+ mkdirSync33(destDir, { recursive: true });
52130
52130
  copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
52131
52131
  copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
52132
52132
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -52965,11 +52965,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
52965
52965
  const models = await fetchModels(peerUrl, authKey);
52966
52966
  if (models.length > 0) {
52967
52967
  try {
52968
- const { writeFileSync: writeFileSync30, mkdirSync: mkdirSync32 } = await import("node:fs");
52969
- const { join: join78, dirname: dirname24 } = await import("node:path");
52970
- const cachePath = join78(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
52971
- mkdirSync32(dirname24(cachePath), { recursive: true });
52972
- writeFileSync30(cachePath, JSON.stringify({
52968
+ const { writeFileSync: writeFileSync31, mkdirSync: mkdirSync33 } = await import("node:fs");
52969
+ const { join: join79, dirname: dirname24 } = await import("node:path");
52970
+ const cachePath = join79(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
52971
+ mkdirSync33(dirname24(cachePath), { recursive: true });
52972
+ writeFileSync31(cachePath, JSON.stringify({
52973
52973
  peerId,
52974
52974
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
52975
52975
  models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
@@ -53168,17 +53168,17 @@ async function handleUpdate(subcommand, ctx) {
53168
53168
  try {
53169
53169
  const { createRequire: createRequire6 } = await import("node:module");
53170
53170
  const { fileURLToPath: fileURLToPath16 } = await import("node:url");
53171
- const { dirname: dirname24, join: join78 } = await import("node:path");
53172
- const { existsSync: existsSync58 } = await import("node:fs");
53171
+ const { dirname: dirname24, join: join79 } = await import("node:path");
53172
+ const { existsSync: existsSync59 } = await import("node:fs");
53173
53173
  const req = createRequire6(import.meta.url);
53174
53174
  const thisDir = dirname24(fileURLToPath16(import.meta.url));
53175
53175
  const candidates = [
53176
- join78(thisDir, "..", "package.json"),
53177
- join78(thisDir, "..", "..", "package.json"),
53178
- join78(thisDir, "..", "..", "..", "package.json")
53176
+ join79(thisDir, "..", "package.json"),
53177
+ join79(thisDir, "..", "..", "package.json"),
53178
+ join79(thisDir, "..", "..", "..", "package.json")
53179
53179
  ];
53180
53180
  for (const pkgPath of candidates) {
53181
- if (existsSync58(pkgPath)) {
53181
+ if (existsSync59(pkgPath)) {
53182
53182
  const pkg = req(pkgPath);
53183
53183
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
53184
53184
  currentVersion = pkg.version ?? "0.0.0";
@@ -54176,11 +54176,11 @@ function getEnvironment(repoRoot) {
54176
54176
  ];
54177
54177
  return lines.join("\n");
54178
54178
  }
54179
- function loadTaskMemories(repoRoot, store) {
54179
+ function loadTaskMemories(repoRoot, store2) {
54180
54180
  try {
54181
- let tasks = store.listByRepo(repoRoot);
54181
+ let tasks = store2.listByRepo(repoRoot);
54182
54182
  if (tasks.length === 0) {
54183
- tasks = store.recent(10);
54183
+ tasks = store2.recent(10);
54184
54184
  }
54185
54185
  if (tasks.length === 0)
54186
54186
  return "";
@@ -54198,9 +54198,9 @@ function loadTaskMemories(repoRoot, store) {
54198
54198
  return "";
54199
54199
  }
54200
54200
  }
54201
- function loadFailurePatterns(store) {
54201
+ function loadFailurePatterns(store2) {
54202
54202
  try {
54203
- const unresolved = store.listUnresolved();
54203
+ const unresolved = store2.listUnresolved();
54204
54204
  if (unresolved.length === 0)
54205
54205
  return "";
54206
54206
  const seen = /* @__PURE__ */ new Set();
@@ -54222,10 +54222,10 @@ function loadFailurePatterns(store) {
54222
54222
  return "";
54223
54223
  }
54224
54224
  }
54225
- function loadPatternSuggestions(repoRoot, store) {
54225
+ function loadPatternSuggestions(repoRoot, store2) {
54226
54226
  try {
54227
- const projectPatterns = store.detectPatterns({ repoRoot, minOccurrences: 3, minLen: 3 });
54228
- const globalPatterns = store.detectPatterns({ minOccurrences: 3, minLen: 3 });
54227
+ const projectPatterns = store2.detectPatterns({ repoRoot, minOccurrences: 3, minLen: 3 });
54228
+ const globalPatterns = store2.detectPatterns({ minOccurrences: 3, minLen: 3 });
54229
54229
  const all = [...projectPatterns];
54230
54230
  for (const gp of globalPatterns) {
54231
54231
  const fp = gp.pattern.map((e) => e.tool).join("->");
@@ -65537,7 +65537,10 @@ body {
65537
65537
  <div id="tabs" style="display:flex;gap:0;background:#1e1e22;border-bottom:1px solid #2a2a30;padding:0 16px;flex-shrink:0">
65538
65538
  <button class="tab active" onclick="switchTab('chat')" id="tab-chat" style="background:none;border:none;border-bottom:2px solid #b2920a;color:#b2920a;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">chat</button>
65539
65539
  <button class="tab" onclick="switchTab('agent')" id="tab-agent" style="background:none;border:none;border-bottom:2px solid transparent;color:#555;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">agent</button>
65540
- <button class="tab" onclick="switchTab('jobs')" id="tab-jobs" style="background:none;border:none;border-bottom:2px solid transparent;color:#555;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">jobs</button>
65540
+ <button class="tab" onclick="switchTab('jobs')" id="tab-jobs" style="background:none;border:none;border-bottom:2px solid transparent;color:#555;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">dashboard</button>
65541
+ <button class="tab" onclick="switchTab('config')" id="tab-config" style="background:none;border:none;border-bottom:2px solid transparent;color:#555;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">config</button>
65542
+ <button class="tab" onclick="switchTab('activity')" id="tab-activity" style="background:none;border:none;border-bottom:2px solid transparent;color:#555;padding:6px 16px;font-family:inherit;font-size:0.7rem;cursor:pointer">activity</button>
65543
+ <span id="token-counter" style="margin-left:auto;font-size:0.6rem;color:#555">0 tokens</span>
65541
65544
  </div>
65542
65545
  <div id="conversation"></div>
65543
65546
  <div id="agent-panel" style="display:none;flex:1;overflow-y:auto;padding:12px 16px">
@@ -65551,10 +65554,41 @@ body {
65551
65554
  </div>
65552
65555
  <div id="jobs-panel" style="display:none;flex:1;overflow-y:auto;padding:12px 16px">
65553
65556
  <div id="dashboard-health" style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap"></div>
65557
+ <div id="dashboard-daemons" style="margin-bottom:16px"></div>
65554
65558
  <div id="dashboard-usage" style="margin-bottom:16px"></div>
65555
65559
  <h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:8px">Job History</h3>
65556
65560
  <div id="jobs-list" style="font-size:0.78rem"></div>
65557
65561
  </div>
65562
+ <div id="config-panel" style="display:none;flex:1;overflow-y:auto;padding:12px 16px">
65563
+ <h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:12px">Server Configuration</h3>
65564
+ <div id="config-content" style="font-size:0.78rem"></div>
65565
+ <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Model</h3>
65566
+ <div style="display:flex;gap:8px;align-items:center">
65567
+ <select id="config-model-select" style="background:#2a2a30;border:1px solid #3a3a42;color:#b0b0b0;padding:4px 8px;border-radius:3px;font-family:inherit;font-size:0.7rem;flex:1"></select>
65568
+ <button onclick="switchModel()" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">switch</button>
65569
+ </div>
65570
+ <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Inference Provider</h3>
65571
+ <div id="config-endpoint" style="font-size:0.78rem;color:#888;margin-bottom:8px"></div>
65572
+ <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:4px">
65573
+ <input id="config-ep-url" placeholder="https://api.example.com/v1" style="flex:1;min-width:200px;background:#2a2a30;border:1px solid #3a3a42;border-radius:3px;padding:4px 8px;color:#b0b0b0;font-family:inherit;font-size:0.7rem;outline:none">
65574
+ <input id="config-ep-key" placeholder="Bearer key (optional)" type="password" style="flex:1;min-width:150px;background:#2a2a30;border:1px solid #3a3a42;border-radius:3px;padding:4px 8px;color:#b0b0b0;font-family:inherit;font-size:0.7rem;outline:none">
65575
+ <select id="config-ep-type" style="background:#2a2a30;border:1px solid #3a3a42;color:#b0b0b0;padding:4px 8px;border-radius:3px;font-family:inherit;font-size:0.7rem">
65576
+ <option value="ollama">ollama</option><option value="vllm">vllm</option><option value="openai">openai</option>
65577
+ </select>
65578
+ <button onclick="switchEndpoint()" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">set</button>
65579
+ </div>
65580
+ <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Profiles</h3>
65581
+ <div id="config-profiles" style="font-size:0.78rem"></div>
65582
+ <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Export Conversation</h3>
65583
+ <div style="display:flex;gap:8px">
65584
+ <button onclick="exportChat('md')" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">markdown</button>
65585
+ <button onclick="exportChat('json')" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">JSON</button>
65586
+ </div>
65587
+ </div>
65588
+ <div id="activity-panel" style="display:none;flex:1;overflow-y:auto;padding:12px 16px">
65589
+ <h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:12px">Recent Activity (Audit Log)</h3>
65590
+ <div id="activity-feed" style="font-size:0.72rem"></div>
65591
+ </div>
65558
65592
 
65559
65593
  <div id="footer">
65560
65594
  <span id="system-prompt-toggle" onclick="toggleSystemPrompt()">sys</span>
@@ -65733,6 +65767,7 @@ async function sendMessage() {
65733
65767
  }
65734
65768
 
65735
65769
  messages.push({ role: 'assistant', content: fullContent });
65770
+ updateTokenCounter(fullContent.split(/\\s+/).length * 1.3 | 0); // rough token estimate
65736
65771
  // Re-render with copy button
65737
65772
  msgDiv.innerHTML = renderMarkdown(fullContent);
65738
65773
  const actions = document.createElement('div');
@@ -65780,16 +65815,150 @@ function closeKeyModal() {
65780
65815
  }
65781
65816
 
65782
65817
  // Tab switching
65818
+ const allPanels = ['conversation','agent-panel','jobs-panel','config-panel','activity-panel'];
65783
65819
  function switchTab(tab) {
65784
- document.getElementById('conversation').style.display = tab === 'chat' ? 'flex' : 'none';
65785
- document.getElementById('agent-panel').style.display = tab === 'agent' ? 'block' : 'none';
65786
- document.getElementById('jobs-panel').style.display = tab === 'jobs' ? 'block' : 'none';
65820
+ const panelMap = {chat:'conversation',agent:'agent-panel',jobs:'jobs-panel',config:'config-panel',activity:'activity-panel'};
65821
+ allPanels.forEach(id => { const el = document.getElementById(id); if(el) el.style.display = 'none'; });
65822
+ const panel = document.getElementById(panelMap[tab]);
65823
+ if (panel) panel.style.display = tab === 'chat' ? 'flex' : 'block';
65787
65824
  document.getElementById('footer').style.display = tab === 'chat' ? 'flex' : 'none';
65788
65825
  document.querySelectorAll('.tab').forEach(t => { t.style.borderBottomColor = 'transparent'; t.style.color = '#555'; });
65789
65826
  const active = document.getElementById('tab-' + tab);
65790
65827
  if (active) { active.style.borderBottomColor = '#b2920a'; active.style.color = '#b2920a'; }
65791
65828
  if (tab === 'jobs') loadJobs();
65792
65829
  if (tab === 'agent') loadProfiles();
65830
+ if (tab === 'config') loadConfig();
65831
+ if (tab === 'activity') loadActivity();
65832
+ }
65833
+
65834
+ // Token counter
65835
+ let totalTokens = 0;
65836
+ function updateTokenCounter(n) { totalTokens += n; document.getElementById('token-counter').textContent = totalTokens.toLocaleString() + ' tokens'; }
65837
+
65838
+ // Config panel
65839
+ async function loadConfig() {
65840
+ try {
65841
+ const [cfg, ep, models] = await Promise.all([
65842
+ fetch('/v1/config', { headers: headers() }).then(r => r.json()),
65843
+ fetch('/v1/config/endpoint', { headers: headers() }).then(r => r.json()),
65844
+ fetch('/v1/models', { headers: headers() }).then(r => r.json()),
65845
+ ]);
65846
+ const c = cfg.config || {};
65847
+ document.getElementById('config-content').innerHTML =
65848
+ '<table style="width:100%">' +
65849
+ Object.entries(c).map(([k,v]) =>
65850
+ '<tr style="border-bottom:1px solid #2a2a30"><td style="padding:4px;color:#888">' + k + '</td>' +
65851
+ '<td style="padding:4px;color:#b0b0b0">' + (v === '[redacted]' ? '<span style="color:#555">[redacted]</span>' : String(v)) + '</td></tr>'
65852
+ ).join('') + '</table>';
65853
+ document.getElementById('config-endpoint').textContent = ep.url + ' (' + (ep.backendType || 'unknown') + ')';
65854
+ // Populate model switcher
65855
+ const sel = document.getElementById('config-model-select');
65856
+ sel.innerHTML = '';
65857
+ for (const m of (models.data || [])) {
65858
+ const opt = document.createElement('option');
65859
+ opt.value = m.id.replace(/^local\\//, '');
65860
+ opt.textContent = m.id.replace(/^local\\//, '');
65861
+ if (opt.value === c.model) opt.selected = true;
65862
+ sel.appendChild(opt);
65863
+ }
65864
+ } catch {}
65865
+ // Profiles
65866
+ try {
65867
+ const r = await fetch('/v1/profiles', { headers: headers() });
65868
+ const d = await r.json();
65869
+ document.getElementById('config-profiles').innerHTML = (d.profiles || []).map(p =>
65870
+ '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:6px 10px;margin:4px 0">' +
65871
+ '<span style="color:#b2920a">' + p.name + '</span>' +
65872
+ (p.encrypted ? ' <span style="color:#555;font-size:0.6rem">(encrypted)</span>' : '') +
65873
+ ' <span style="color:#555;font-size:0.6rem">' + (p.source || '') + '</span></div>'
65874
+ ).join('') || '<span style="color:#555">No profiles</span>';
65875
+ } catch {}
65876
+ }
65877
+
65878
+ async function switchEndpoint() {
65879
+ const url = document.getElementById('config-ep-url').value.trim();
65880
+ const auth = document.getElementById('config-ep-key').value.trim();
65881
+ const backendType = document.getElementById('config-ep-type').value;
65882
+ if (!url) return;
65883
+ try {
65884
+ await fetch('/v1/config/endpoint', {
65885
+ method: 'PUT', headers: headers(),
65886
+ body: JSON.stringify({ url, auth: auth ? 'Bearer ' + auth : '', backendType }),
65887
+ });
65888
+ loadConfig();
65889
+ loadModels(); // refresh model list from new endpoint
65890
+ } catch {}
65891
+ }
65892
+
65893
+ async function switchModel() {
65894
+ const model = document.getElementById('config-model-select').value;
65895
+ if (!model) return;
65896
+ try {
65897
+ await fetch('/v1/config/model', {
65898
+ method: 'PUT', headers: headers(),
65899
+ body: JSON.stringify({ model }),
65900
+ });
65901
+ loadConfig();
65902
+ modelSelect.value = model; // sync chat model picker
65903
+ } catch {}
65904
+ }
65905
+
65906
+ // Export conversation
65907
+ function exportChat(fmt) {
65908
+ let content;
65909
+ if (fmt === 'json') {
65910
+ content = JSON.stringify(messages, null, 2);
65911
+ } else {
65912
+ content = messages.map(m => (m.role === 'user' ? '**You:** ' : '**Agent:** ') + m.content).join('\\n\\n');
65913
+ }
65914
+ const blob = new Blob([content], { type: fmt === 'json' ? 'application/json' : 'text/markdown' });
65915
+ const a = document.createElement('a');
65916
+ a.href = URL.createObjectURL(blob);
65917
+ a.download = 'conversation.' + (fmt === 'json' ? 'json' : 'md');
65918
+ a.click();
65919
+ }
65920
+
65921
+ // Activity feed (audit log)
65922
+ async function loadActivity() {
65923
+ try {
65924
+ const r = await fetch('/v1/audit?limit=50', { headers: headers() });
65925
+ const d = await r.json();
65926
+ const feed = document.getElementById('activity-feed');
65927
+ if (!d.records?.length) { feed.innerHTML = '<span style="color:#555">No activity yet</span>'; return; }
65928
+ feed.innerHTML = d.records.map(r => {
65929
+ const time = r.ts?.split('T')[1]?.slice(0,8) || '';
65930
+ const color = r.status >= 400 ? '#ff4444' : r.status >= 300 ? '#b2920a' : '#4ec94e';
65931
+ return '<div style="padding:3px 0;border-bottom:1px solid #1e1e22">' +
65932
+ '<span style="color:#555">' + time + '</span> ' +
65933
+ '<span style="color:' + color + '">' + r.status + '</span> ' +
65934
+ '<span style="color:#888">' + r.method + '</span> ' +
65935
+ '<span style="color:#b0b0b0">' + r.path + '</span> ' +
65936
+ '<span style="color:#555">' + r.latencyMs + 'ms</span> ' +
65937
+ '<span style="color:#555;font-size:0.6rem">' + (r.user || '') + '</span></div>';
65938
+ }).join('');
65939
+ } catch {}
65940
+ }
65941
+
65942
+ // Daemon monitor (on dashboard tab)
65943
+ async function loadDaemons() {
65944
+ // The daemon registry is server-side (TUI). We can't query it via REST yet.
65945
+ // Show running jobs as a proxy for active processes.
65946
+ try {
65947
+ const r = await fetch('/v1/runs?status=running', { headers: headers() });
65948
+ const d = await r.json();
65949
+ const el = document.getElementById('dashboard-daemons');
65950
+ if (!d.runs?.length) {
65951
+ el.innerHTML = '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;color:#555;font-size:0.7rem">No active processes</div>';
65952
+ return;
65953
+ }
65954
+ el.innerHTML = '<h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:8px">Active Processes</h3>' +
65955
+ d.runs.map(j =>
65956
+ '<div style="background:#1e1e22;border-left:2px solid #b2920a;padding:6px 10px;margin:4px 0;font-size:0.72rem">' +
65957
+ '<span style="color:#b2920a">' + (j.id||'').slice(0,12) + '</span> ' +
65958
+ '<span style="color:#4ec94e">running</span> ' +
65959
+ '<span style="color:#888">' + (j.task||'').slice(0,50) + '</span></div>'
65960
+ ).join('');
65961
+ } catch {}
65793
65962
  }
65794
65963
 
65795
65964
  // Agent task
@@ -65892,24 +66061,45 @@ async function loadDashboard() {
65892
66061
  '<div style="color:#555;font-size:0.6rem">VERSION</div>' +
65893
66062
  '<div style="color:#b0b0b0;font-size:0.8rem">' + d.version + '</div></div>';
65894
66063
  } catch {}
65895
- // Usage
66064
+ // Usage \u2014 per-provider breakdown with persistent totals
65896
66065
  try {
65897
66066
  const r = await fetch('/v1/usage', { headers: headers() });
65898
66067
  const d = await r.json();
66068
+ const ps = d.persistent?.byProvider || {};
66069
+ let providerCards = '';
66070
+ for (const [label, stats] of Object.entries(ps)) {
66071
+ const s = stats;
66072
+ providerCards +=
66073
+ '<div style="background:#1e1e22;border-left:2px solid #b2920a;padding:8px 12px;margin:4px 0">' +
66074
+ '<div style="color:#b2920a;font-size:0.7rem;font-weight:bold">' + label + '</div>' +
66075
+ '<div style="display:flex;gap:16px;margin-top:4px">' +
66076
+ '<span style="color:#555;font-size:0.65rem">in: <span style="color:#b0b0b0">' + (s.tokensIn || 0).toLocaleString() + '</span></span>' +
66077
+ '<span style="color:#555;font-size:0.65rem">out: <span style="color:#b0b0b0">' + (s.tokensOut || 0).toLocaleString() + '</span></span>' +
66078
+ '<span style="color:#555;font-size:0.65rem">reqs: <span style="color:#b0b0b0">' + (s.requests || 0).toLocaleString() + '</span></span>' +
66079
+ '</div></div>';
66080
+ }
66081
+ const totalIn = d.persistent?.totalIn || d.totalTokensIn || 0;
66082
+ const totalOut = d.persistent?.totalOut || d.totalTokensOut || 0;
65899
66083
  document.getElementById('dashboard-usage').innerHTML =
65900
- '<div style="display:flex;gap:12px;flex-wrap:wrap">' +
66084
+ '<h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:8px">Token Usage by Provider (persistent)</h3>' +
66085
+ '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:8px">' +
66086
+ '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
66087
+ '<div style="color:#555;font-size:0.6rem">TOTAL IN</div>' +
66088
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalIn.toLocaleString() + '</div></div>' +
65901
66089
  '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
65902
- '<div style="color:#555;font-size:0.6rem">TOKENS IN</div>' +
65903
- '<div style="color:#b2920a;font-size:0.8rem">' + (d.totalTokensIn || 0).toLocaleString() + '</div></div>' +
66090
+ '<div style="color:#555;font-size:0.6rem">TOTAL OUT</div>' +
66091
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalOut.toLocaleString() + '</div></div>' +
65904
66092
  '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
65905
- '<div style="color:#555;font-size:0.6rem">TOKENS OUT</div>' +
65906
- '<div style="color:#b2920a;font-size:0.8rem">' + (d.totalTokensOut || 0).toLocaleString() + '</div></div>' +
65907
- '</div>';
66093
+ '<div style="color:#555;font-size:0.6rem">TOTAL REQUESTS</div>' +
66094
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + (d.persistent?.totalRequests || 0).toLocaleString() + '</div></div>' +
66095
+ '</div>' +
66096
+ (providerCards || '<div style="color:#555;font-size:0.7rem">No provider usage recorded yet</div>');
65908
66097
  } catch {}
65909
66098
  }
65910
66099
 
65911
66100
  async function loadJobs() {
65912
66101
  loadDashboard();
66102
+ loadDaemons();
65913
66103
  const list = document.getElementById('jobs-list');
65914
66104
  try {
65915
66105
  const r = await fetch('/v1/runs', { headers: headers() });
@@ -66069,25 +66259,101 @@ var init_auth_oidc = __esm({
66069
66259
  }
66070
66260
  });
66071
66261
 
66072
- // packages/cli/dist/api/profiles.js
66073
- import { existsSync as existsSync53, readFileSync as readFileSync42, writeFileSync as writeFileSync25, mkdirSync as mkdirSync27, readdirSync as readdirSync20, unlinkSync as unlinkSync12 } from "node:fs";
66262
+ // packages/cli/dist/api/usage-tracker.js
66263
+ import { mkdirSync as mkdirSync27, readFileSync as readFileSync42, writeFileSync as writeFileSync25, existsSync as existsSync53 } from "node:fs";
66074
66264
  import { join as join70 } from "node:path";
66265
+ function initUsageTracker(oaDir) {
66266
+ const dir = join70(oaDir, "usage");
66267
+ mkdirSync27(dir, { recursive: true });
66268
+ usageFile = join70(dir, "token-usage.json");
66269
+ try {
66270
+ if (existsSync53(usageFile)) {
66271
+ store = JSON.parse(readFileSync42(usageFile, "utf-8"));
66272
+ }
66273
+ } catch {
66274
+ store = { providers: {}, lastSaved: "" };
66275
+ }
66276
+ initialized2 = true;
66277
+ setInterval(() => {
66278
+ if (dirty)
66279
+ flush();
66280
+ }, 3e4);
66281
+ }
66282
+ function ensureProvider(label) {
66283
+ if (!store.providers[label]) {
66284
+ store.providers[label] = { tokensIn: 0, tokensOut: 0, requests: 0, byDay: {} };
66285
+ }
66286
+ return store.providers[label];
66287
+ }
66288
+ function today() {
66289
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66290
+ }
66291
+ function trackTokens(provider, tokensIn, tokensOut) {
66292
+ if (!initialized2)
66293
+ return;
66294
+ const p = ensureProvider(provider);
66295
+ p.tokensIn += tokensIn;
66296
+ p.tokensOut += tokensOut;
66297
+ p.requests++;
66298
+ const day = today();
66299
+ if (!p.byDay[day])
66300
+ p.byDay[day] = { in: 0, out: 0, reqs: 0 };
66301
+ p.byDay[day].in += tokensIn;
66302
+ p.byDay[day].out += tokensOut;
66303
+ p.byDay[day].reqs++;
66304
+ dirty = true;
66305
+ }
66306
+ function flush() {
66307
+ if (!initialized2 || !dirty)
66308
+ return;
66309
+ try {
66310
+ store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
66311
+ writeFileSync25(usageFile, JSON.stringify(store, null, 2), "utf-8");
66312
+ dirty = false;
66313
+ } catch {
66314
+ }
66315
+ }
66316
+ function getUsageSummary() {
66317
+ let totalIn = 0, totalOut = 0, totalRequests = 0;
66318
+ const byProvider = {};
66319
+ for (const [label, p] of Object.entries(store.providers)) {
66320
+ totalIn += p.tokensIn;
66321
+ totalOut += p.tokensOut;
66322
+ totalRequests += p.requests;
66323
+ byProvider[label] = { tokensIn: p.tokensIn, tokensOut: p.tokensOut, requests: p.requests };
66324
+ }
66325
+ return { totalIn, totalOut, totalRequests, byProvider };
66326
+ }
66327
+ var store, usageFile, dirty, initialized2;
66328
+ var init_usage_tracker = __esm({
66329
+ "packages/cli/dist/api/usage-tracker.js"() {
66330
+ "use strict";
66331
+ store = { providers: {}, lastSaved: "" };
66332
+ usageFile = "";
66333
+ dirty = false;
66334
+ initialized2 = false;
66335
+ }
66336
+ });
66337
+
66338
+ // packages/cli/dist/api/profiles.js
66339
+ import { existsSync as existsSync54, readFileSync as readFileSync43, writeFileSync as writeFileSync26, mkdirSync as mkdirSync28, readdirSync as readdirSync20, unlinkSync as unlinkSync12 } from "node:fs";
66340
+ import { join as join71 } from "node:path";
66075
66341
  import { homedir as homedir18 } from "node:os";
66076
66342
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
66077
66343
  function globalProfileDir() {
66078
- return join70(homedir18(), ".open-agents", "profiles");
66344
+ return join71(homedir18(), ".open-agents", "profiles");
66079
66345
  }
66080
66346
  function projectProfileDir(projectDir) {
66081
- return join70(projectDir || process.cwd(), ".oa", "profiles");
66347
+ return join71(projectDir || process.cwd(), ".oa", "profiles");
66082
66348
  }
66083
66349
  function listProfiles(projectDir) {
66084
66350
  const result = [];
66085
66351
  const seen = /* @__PURE__ */ new Set();
66086
66352
  const projDir = projectProfileDir(projectDir);
66087
- if (existsSync53(projDir)) {
66353
+ if (existsSync54(projDir)) {
66088
66354
  for (const f of readdirSync20(projDir).filter((f2) => f2.endsWith(".json"))) {
66089
66355
  try {
66090
- const raw = JSON.parse(readFileSync42(join70(projDir, f), "utf8"));
66356
+ const raw = JSON.parse(readFileSync43(join71(projDir, f), "utf8"));
66091
66357
  const name = f.replace(".json", "");
66092
66358
  seen.add(name);
66093
66359
  result.push({
@@ -66101,13 +66367,13 @@ function listProfiles(projectDir) {
66101
66367
  }
66102
66368
  }
66103
66369
  const globDir = globalProfileDir();
66104
- if (existsSync53(globDir)) {
66370
+ if (existsSync54(globDir)) {
66105
66371
  for (const f of readdirSync20(globDir).filter((f2) => f2.endsWith(".json"))) {
66106
66372
  const name = f.replace(".json", "");
66107
66373
  if (seen.has(name))
66108
66374
  continue;
66109
66375
  try {
66110
- const raw = JSON.parse(readFileSync42(join70(globDir, f), "utf8"));
66376
+ const raw = JSON.parse(readFileSync43(join71(globDir, f), "utf8"));
66111
66377
  result.push({
66112
66378
  name,
66113
66379
  description: raw.description || "",
@@ -66122,12 +66388,12 @@ function listProfiles(projectDir) {
66122
66388
  }
66123
66389
  function loadProfile(name, password, projectDir) {
66124
66390
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
66125
- const projPath = join70(projectProfileDir(projectDir), `${sanitized}.json`);
66126
- const globPath = join70(globalProfileDir(), `${sanitized}.json`);
66127
- const filePath = existsSync53(projPath) ? projPath : existsSync53(globPath) ? globPath : null;
66391
+ const projPath = join71(projectProfileDir(projectDir), `${sanitized}.json`);
66392
+ const globPath = join71(globalProfileDir(), `${sanitized}.json`);
66393
+ const filePath = existsSync54(projPath) ? projPath : existsSync54(globPath) ? globPath : null;
66128
66394
  if (!filePath)
66129
66395
  return null;
66130
- const raw = JSON.parse(readFileSync42(filePath, "utf8"));
66396
+ const raw = JSON.parse(readFileSync43(filePath, "utf8"));
66131
66397
  if (raw.encrypted === true) {
66132
66398
  if (!password)
66133
66399
  return null;
@@ -66137,23 +66403,23 @@ function loadProfile(name, password, projectDir) {
66137
66403
  }
66138
66404
  function saveProfile(profile, password, scope = "global", projectDir) {
66139
66405
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
66140
- mkdirSync27(dir, { recursive: true });
66406
+ mkdirSync28(dir, { recursive: true });
66141
66407
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
66142
- const filePath = join70(dir, `${sanitized}.json`);
66408
+ const filePath = join71(dir, `${sanitized}.json`);
66143
66409
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
66144
66410
  if (password) {
66145
66411
  const encrypted = encryptProfile(profile, password);
66146
- writeFileSync25(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
66412
+ writeFileSync26(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
66147
66413
  } else {
66148
66414
  profile.encrypted = false;
66149
- writeFileSync25(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
66415
+ writeFileSync26(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
66150
66416
  }
66151
66417
  }
66152
66418
  function deleteProfile(name, scope = "global", projectDir) {
66153
66419
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
66154
66420
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
66155
- const filePath = join70(dir, `${sanitized}.json`);
66156
- if (existsSync53(filePath)) {
66421
+ const filePath = join71(dir, `${sanitized}.json`);
66422
+ if (existsSync54(filePath)) {
66157
66423
  unlinkSync12(filePath);
66158
66424
  return true;
66159
66425
  }
@@ -66246,22 +66512,22 @@ import * as http from "node:http";
66246
66512
  import * as https from "node:https";
66247
66513
  import { createRequire as createRequire3 } from "node:module";
66248
66514
  import { fileURLToPath as fileURLToPath13 } from "node:url";
66249
- import { dirname as dirname21, join as join71, resolve as resolve31 } from "node:path";
66515
+ import { dirname as dirname21, join as join72, resolve as resolve31 } from "node:path";
66250
66516
  import { spawn as spawn21 } from "node:child_process";
66251
- import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync26, readFileSync as readFileSync43, readdirSync as readdirSync21, existsSync as existsSync54 } from "node:fs";
66517
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync27, readFileSync as readFileSync44, readdirSync as readdirSync21, existsSync as existsSync55 } from "node:fs";
66252
66518
  import { randomBytes as randomBytes16, randomUUID as randomUUID4 } from "node:crypto";
66253
66519
  function getVersion3() {
66254
66520
  try {
66255
66521
  const require2 = createRequire3(import.meta.url);
66256
66522
  const thisDir = dirname21(fileURLToPath13(import.meta.url));
66257
66523
  const candidates = [
66258
- join71(thisDir, "..", "package.json"),
66259
- join71(thisDir, "..", "..", "package.json"),
66260
- join71(thisDir, "..", "..", "..", "package.json")
66524
+ join72(thisDir, "..", "package.json"),
66525
+ join72(thisDir, "..", "..", "package.json"),
66526
+ join72(thisDir, "..", "..", "..", "package.json")
66261
66527
  ];
66262
66528
  for (const pkgPath of candidates) {
66263
66529
  try {
66264
- if (!existsSync54(pkgPath))
66530
+ if (!existsSync55(pkgPath))
66265
66531
  continue;
66266
66532
  const pkg = require2(pkgPath);
66267
66533
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
@@ -66277,14 +66543,14 @@ function getVersion3() {
66277
66543
  }
66278
66544
  function getEndpointUsage(label) {
66279
66545
  let u = endpointUsage.get(label);
66280
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66546
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66281
66547
  if (!u) {
66282
- u = { requestTimestamps: [], tokensToday: 0, tokenDate: today };
66548
+ u = { requestTimestamps: [], tokensToday: 0, tokenDate: today2 };
66283
66549
  endpointUsage.set(label, u);
66284
66550
  }
66285
- if (u.tokenDate !== today) {
66551
+ if (u.tokenDate !== today2) {
66286
66552
  u.tokensToday = 0;
66287
- u.tokenDate = today;
66553
+ u.tokenDate = today2;
66288
66554
  }
66289
66555
  return u;
66290
66556
  }
@@ -66562,29 +66828,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
66562
66828
  }
66563
66829
  function jobsDir() {
66564
66830
  const root = resolve31(process.cwd());
66565
- const dir = join71(root, ".oa", "jobs");
66566
- mkdirSync28(dir, { recursive: true });
66831
+ const dir = join72(root, ".oa", "jobs");
66832
+ mkdirSync29(dir, { recursive: true });
66567
66833
  return dir;
66568
66834
  }
66569
66835
  function loadJob(id) {
66570
- const file = join71(jobsDir(), `${id}.json`);
66571
- if (!existsSync54(file))
66836
+ const file = join72(jobsDir(), `${id}.json`);
66837
+ if (!existsSync55(file))
66572
66838
  return null;
66573
66839
  try {
66574
- return JSON.parse(readFileSync43(file, "utf-8"));
66840
+ return JSON.parse(readFileSync44(file, "utf-8"));
66575
66841
  } catch {
66576
66842
  return null;
66577
66843
  }
66578
66844
  }
66579
66845
  function listJobs() {
66580
66846
  const dir = jobsDir();
66581
- if (!existsSync54(dir))
66847
+ if (!existsSync55(dir))
66582
66848
  return [];
66583
66849
  const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).sort();
66584
66850
  const jobs = [];
66585
66851
  for (const file of files) {
66586
66852
  try {
66587
- jobs.push(JSON.parse(readFileSync43(join71(dir, file), "utf-8")));
66853
+ jobs.push(JSON.parse(readFileSync44(join72(dir, file), "utf-8")));
66588
66854
  } catch {
66589
66855
  }
66590
66856
  }
@@ -66595,10 +66861,10 @@ function getKeyUsage(user) {
66595
66861
  perKeyUsage.set(user, { requestTimestamps: [], tokensToday: 0, tokenDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), activeJobs: 0 });
66596
66862
  }
66597
66863
  const u = perKeyUsage.get(user);
66598
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66599
- if (u.tokenDate !== today) {
66864
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66865
+ if (u.tokenDate !== today2) {
66600
66866
  u.tokensToday = 0;
66601
- u.tokenDate = today;
66867
+ u.tokenDate = today2;
66602
66868
  }
66603
66869
  return u;
66604
66870
  }
@@ -66777,8 +67043,11 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66777
67043
  const parsed = JSON.parse(result.body);
66778
67044
  if (parsed.usage) {
66779
67045
  const totalTok = (parsed.usage.prompt_tokens ?? 0) + (parsed.usage.completion_tokens ?? 0);
66780
- metrics.totalTokensIn += parsed.usage.prompt_tokens ?? 0;
66781
- metrics.totalTokensOut += parsed.usage.completion_tokens ?? 0;
67046
+ const _pIn = parsed.usage.prompt_tokens ?? 0;
67047
+ const _pOut = parsed.usage.completion_tokens ?? 0;
67048
+ metrics.totalTokensIn += _pIn;
67049
+ metrics.totalTokensOut += _pOut;
67050
+ trackTokens(route?.endpoint?.label ?? "local", _pIn, _pOut);
66782
67051
  if (route?.endpoint)
66783
67052
  recordEndpointUsage(route.endpoint.label, totalTok);
66784
67053
  }
@@ -66816,6 +67085,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66816
67085
  metrics.totalTokensOut += ollamaChunk.eval_count;
66817
67086
  if (ollamaChunk.prompt_eval_count)
66818
67087
  metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
67088
+ trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
66819
67089
  const doneEvent = {
66820
67090
  id: chatId,
66821
67091
  object: "chat.completion.chunk",
@@ -66866,6 +67136,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66866
67136
  metrics.totalTokensOut += ollamaChunk.eval_count;
66867
67137
  if (ollamaChunk.prompt_eval_count)
66868
67138
  metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
67139
+ trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
66869
67140
  res.write(`data: ${JSON.stringify({
66870
67141
  id: chatId,
66871
67142
  object: "chat.completion.chunk",
@@ -66905,6 +67176,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66905
67176
  metrics.totalTokensOut += ollamaResp.eval_count;
66906
67177
  if (ollamaResp.prompt_eval_count)
66907
67178
  metrics.totalTokensIn += ollamaResp.prompt_eval_count;
67179
+ trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
66908
67180
  const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
66909
67181
  const openaiResponse = {
66910
67182
  id: chatId,
@@ -67026,8 +67298,8 @@ async function handleV1Run(req, res) {
67026
67298
  if (workingDir) {
67027
67299
  cwd4 = resolve31(workingDir);
67028
67300
  } else if (isolate) {
67029
- const wsDir = join71(dir, "..", "workspaces", id);
67030
- mkdirSync28(wsDir, { recursive: true });
67301
+ const wsDir = join72(dir, "..", "workspaces", id);
67302
+ mkdirSync29(wsDir, { recursive: true });
67031
67303
  cwd4 = wsDir;
67032
67304
  } else {
67033
67305
  cwd4 = resolve31(process.cwd());
@@ -67099,7 +67371,7 @@ async function handleV1Run(req, res) {
67099
67371
  });
67100
67372
  child.unref();
67101
67373
  job.pid = child.pid ?? 0;
67102
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67374
+ writeFileSync27(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
67103
67375
  runningProcesses.set(id, child);
67104
67376
  if (streamMode) {
67105
67377
  res.writeHead(200, {
@@ -67126,7 +67398,7 @@ async function handleV1Run(req, res) {
67126
67398
  job.status = code === 0 ? "completed" : "failed";
67127
67399
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
67128
67400
  try {
67129
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67401
+ writeFileSync27(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
67130
67402
  } catch {
67131
67403
  }
67132
67404
  runningProcesses.delete(id);
@@ -67157,7 +67429,7 @@ async function handleV1Run(req, res) {
67157
67429
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
67158
67430
  }
67159
67431
  try {
67160
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67432
+ writeFileSync27(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
67161
67433
  } catch {
67162
67434
  }
67163
67435
  runningProcesses.delete(id);
@@ -67206,7 +67478,7 @@ function handleV1RunsDelete(res, id) {
67206
67478
  job.error = "Aborted via API";
67207
67479
  const dir = jobsDir();
67208
67480
  try {
67209
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67481
+ writeFileSync27(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
67210
67482
  } catch {
67211
67483
  }
67212
67484
  runningProcesses.delete(id);
@@ -67492,7 +67764,14 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67492
67764
  limits: ep.limits ?? { maxRequestsPerMinute: "unlimited", maxTokensPerDay: "unlimited" }
67493
67765
  };
67494
67766
  }
67495
- jsonResponse(res, 200, { usage: usageData, totalTokensIn: metrics.totalTokensIn, totalTokensOut: metrics.totalTokensOut });
67767
+ const persistent = getUsageSummary();
67768
+ jsonResponse(res, 200, {
67769
+ usage: usageData,
67770
+ totalTokensIn: metrics.totalTokensIn,
67771
+ totalTokensOut: metrics.totalTokensOut,
67772
+ persistent
67773
+ // survives restarts
67774
+ });
67496
67775
  return;
67497
67776
  }
67498
67777
  if (pathname === "/v1/commands" && method === "GET") {
@@ -67641,19 +67920,20 @@ function startApiServer(options = {}) {
67641
67920
  const config = loadConfig();
67642
67921
  const ollamaUrl = options.ollamaUrl ?? config.backendUrl;
67643
67922
  const cwd4 = process.cwd();
67644
- initAuditLog(join71(cwd4, ".oa"));
67923
+ initAuditLog(join72(cwd4, ".oa"));
67924
+ initUsageTracker(join72(cwd4, ".oa"));
67645
67925
  const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
67646
67926
  if (retentionDays > 0) {
67647
67927
  try {
67648
- const jobsDir3 = join71(cwd4, ".oa", "jobs");
67649
- if (existsSync54(jobsDir3)) {
67928
+ const jobsDir3 = join72(cwd4, ".oa", "jobs");
67929
+ if (existsSync55(jobsDir3)) {
67650
67930
  const cutoff = Date.now() - retentionDays * 864e5;
67651
67931
  for (const f of readdirSync21(jobsDir3)) {
67652
67932
  if (!f.endsWith(".json"))
67653
67933
  continue;
67654
67934
  try {
67655
- const jobPath = join71(jobsDir3, f);
67656
- const job = JSON.parse(readFileSync43(jobPath, "utf-8"));
67935
+ const jobPath = join72(jobsDir3, f);
67936
+ const job = JSON.parse(readFileSync44(jobPath, "utf-8"));
67657
67937
  const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
67658
67938
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
67659
67939
  const { unlinkSync: unlinkSync13 } = __require("node:fs");
@@ -67673,8 +67953,8 @@ function startApiServer(options = {}) {
67673
67953
  if (useTls) {
67674
67954
  try {
67675
67955
  tlsOpts = {
67676
- cert: readFileSync43(resolve31(tlsCert)),
67677
- key: readFileSync43(resolve31(tlsKey))
67956
+ cert: readFileSync44(resolve31(tlsCert)),
67957
+ key: readFileSync44(resolve31(tlsKey))
67678
67958
  };
67679
67959
  } catch (e) {
67680
67960
  log2(`
@@ -67824,6 +68104,7 @@ var init_serve = __esm({
67824
68104
  init_logger();
67825
68105
  init_openapi();
67826
68106
  init_auth_oidc();
68107
+ init_usage_tracker();
67827
68108
  init_oa_directory();
67828
68109
  init_render();
67829
68110
  init_profiles();
@@ -67846,11 +68127,11 @@ var init_serve = __esm({
67846
68127
 
67847
68128
  // packages/cli/dist/tui/interactive.js
67848
68129
  import { cwd } from "node:process";
67849
- import { resolve as resolve32, join as join72, dirname as dirname22, extname as extname11 } from "node:path";
68130
+ import { resolve as resolve32, join as join73, dirname as dirname22, extname as extname11 } from "node:path";
67850
68131
  import { createRequire as createRequire4 } from "node:module";
67851
68132
  import { fileURLToPath as fileURLToPath14 } from "node:url";
67852
- import { readFileSync as readFileSync44, writeFileSync as writeFileSync27, appendFileSync as appendFileSync5, rmSync as rmSync3, readdirSync as readdirSync22, mkdirSync as mkdirSync29 } from "node:fs";
67853
- import { existsSync as existsSync55 } from "node:fs";
68133
+ import { readFileSync as readFileSync45, writeFileSync as writeFileSync28, appendFileSync as appendFileSync5, rmSync as rmSync3, readdirSync as readdirSync22, mkdirSync as mkdirSync30 } from "node:fs";
68134
+ import { existsSync as existsSync56 } from "node:fs";
67854
68135
  import { execSync as execSync35 } from "node:child_process";
67855
68136
  import { homedir as homedir19 } from "node:os";
67856
68137
  function formatTimeAgo(date) {
@@ -67871,12 +68152,12 @@ function getVersion4() {
67871
68152
  const require2 = createRequire4(import.meta.url);
67872
68153
  const thisDir = dirname22(fileURLToPath14(import.meta.url));
67873
68154
  const candidates = [
67874
- join72(thisDir, "..", "package.json"),
67875
- join72(thisDir, "..", "..", "package.json"),
67876
- join72(thisDir, "..", "..", "..", "package.json")
68155
+ join73(thisDir, "..", "package.json"),
68156
+ join73(thisDir, "..", "..", "package.json"),
68157
+ join73(thisDir, "..", "..", "..", "package.json")
67877
68158
  ];
67878
68159
  for (const pkgPath of candidates) {
67879
- if (existsSync55(pkgPath)) {
68160
+ if (existsSync56(pkgPath)) {
67880
68161
  const pkg = require2(pkgPath);
67881
68162
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
67882
68163
  return pkg.version ?? "0.0.0";
@@ -68115,15 +68396,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
68115
68396
  function gatherMemorySnippets(root) {
68116
68397
  const snippets = [];
68117
68398
  const dirs = [
68118
- join72(root, ".oa", "memory"),
68119
- join72(root, ".open-agents", "memory")
68399
+ join73(root, ".oa", "memory"),
68400
+ join73(root, ".open-agents", "memory")
68120
68401
  ];
68121
68402
  for (const dir of dirs) {
68122
- if (!existsSync55(dir))
68403
+ if (!existsSync56(dir))
68123
68404
  continue;
68124
68405
  try {
68125
68406
  for (const f of readdirSync22(dir).filter((f2) => f2.endsWith(".json"))) {
68126
- const data = JSON.parse(readFileSync44(join72(dir, f), "utf-8"));
68407
+ const data = JSON.parse(readFileSync45(join73(dir, f), "utf-8"));
68127
68408
  for (const val of Object.values(data)) {
68128
68409
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
68129
68410
  if (v.length > 10)
@@ -68280,9 +68561,9 @@ ${metabolismMemories}
68280
68561
  } catch {
68281
68562
  }
68282
68563
  try {
68283
- const archeFile = join72(repoRoot, ".oa", "arche", "variants.json");
68284
- if (existsSync55(archeFile)) {
68285
- const variants = JSON.parse(readFileSync44(archeFile, "utf8"));
68564
+ const archeFile = join73(repoRoot, ".oa", "arche", "variants.json");
68565
+ if (existsSync56(archeFile)) {
68566
+ const variants = JSON.parse(readFileSync45(archeFile, "utf8"));
68286
68567
  if (variants.length > 0) {
68287
68568
  let filtered = variants;
68288
68569
  if (taskType) {
@@ -68451,9 +68732,9 @@ RULES:
68451
68732
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
68452
68733
  let identityInjection = "";
68453
68734
  try {
68454
- const ikStateFile = join72(repoRoot, ".oa", "identity", "self-state.json");
68455
- if (existsSync55(ikStateFile)) {
68456
- const selfState = JSON.parse(readFileSync44(ikStateFile, "utf8"));
68735
+ const ikStateFile = join73(repoRoot, ".oa", "identity", "self-state.json");
68736
+ if (existsSync56(ikStateFile)) {
68737
+ const selfState = JSON.parse(readFileSync45(ikStateFile, "utf8"));
68457
68738
  const lines = [
68458
68739
  `[Identity State v${selfState.version}]`,
68459
68740
  `Self: ${selfState.narrative_summary}`,
@@ -69097,13 +69378,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69097
69378
  });
69098
69379
  }
69099
69380
  try {
69100
- const ikDir = join72(repoRoot, ".oa", "identity");
69101
- const ikFile = join72(ikDir, "self-state.json");
69381
+ const ikDir = join73(repoRoot, ".oa", "identity");
69382
+ const ikFile = join73(ikDir, "self-state.json");
69102
69383
  let ikState;
69103
- if (existsSync55(ikFile)) {
69104
- ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
69384
+ if (existsSync56(ikFile)) {
69385
+ ikState = JSON.parse(readFileSync45(ikFile, "utf8"));
69105
69386
  } else {
69106
- mkdirSync29(ikDir, { recursive: true });
69387
+ mkdirSync30(ikDir, { recursive: true });
69107
69388
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
69108
69389
  ikState = {
69109
69390
  self_id: `oa-${machineId}`,
@@ -69129,7 +69410,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69129
69410
  }
69130
69411
  ikState.session_count = (ikState.session_count || 0) + 1;
69131
69412
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69132
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69413
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
69133
69414
  } catch (ikErr) {
69134
69415
  try {
69135
69416
  console.error("[IK-OBSERVE]", ikErr);
@@ -69144,14 +69425,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69144
69425
  } else {
69145
69426
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
69146
69427
  try {
69147
- const ikFile = join72(repoRoot, ".oa", "identity", "self-state.json");
69148
- if (existsSync55(ikFile)) {
69149
- const ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
69428
+ const ikFile = join73(repoRoot, ".oa", "identity", "self-state.json");
69429
+ if (existsSync56(ikFile)) {
69430
+ const ikState = JSON.parse(readFileSync45(ikFile, "utf8"));
69150
69431
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
69151
69432
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
69152
69433
  ikState.session_count = (ikState.session_count || 0) + 1;
69153
69434
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69154
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69435
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
69155
69436
  }
69156
69437
  } catch {
69157
69438
  }
@@ -69248,10 +69529,10 @@ async function startInteractive(config, repoPath) {
69248
69529
  process.stdin.pause();
69249
69530
  }
69250
69531
  try {
69251
- const oaDir = join72(repoRoot, ".oa");
69252
- const nexusPidFile = join72(oaDir, "nexus", "daemon.pid");
69253
- if (existsSync55(nexusPidFile)) {
69254
- const pid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
69532
+ const oaDir = join73(repoRoot, ".oa");
69533
+ const nexusPidFile = join73(oaDir, "nexus", "daemon.pid");
69534
+ if (existsSync56(nexusPidFile)) {
69535
+ const pid = parseInt(readFileSync45(nexusPidFile, "utf8").trim(), 10);
69255
69536
  if (pid > 0) {
69256
69537
  try {
69257
69538
  process.kill(pid, 0);
@@ -69588,7 +69869,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
69588
69869
  let p2pGateway = null;
69589
69870
  let peerMesh = null;
69590
69871
  let inferenceRouter = null;
69591
- const secretVault = new SecretVault(join72(repoRoot, ".oa", "vault.enc"));
69872
+ const secretVault = new SecretVault(join73(repoRoot, ".oa", "vault.enc"));
69592
69873
  let adminSessionKey = null;
69593
69874
  const callSubAgents = /* @__PURE__ */ new Map();
69594
69875
  const streamRenderer = new StreamRenderer();
@@ -69811,13 +70092,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
69811
70092
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
69812
70093
  return [hits, line];
69813
70094
  }
69814
- const HISTORY_DIR = join72(homedir19(), ".open-agents");
69815
- const HISTORY_FILE = join72(HISTORY_DIR, "repl-history");
70095
+ const HISTORY_DIR = join73(homedir19(), ".open-agents");
70096
+ const HISTORY_FILE = join73(HISTORY_DIR, "repl-history");
69816
70097
  const MAX_HISTORY_LINES = 500;
69817
70098
  let savedHistory = [];
69818
70099
  try {
69819
- if (existsSync55(HISTORY_FILE)) {
69820
- const raw = readFileSync44(HISTORY_FILE, "utf8").trim();
70100
+ if (existsSync56(HISTORY_FILE)) {
70101
+ const raw = readFileSync45(HISTORY_FILE, "utf8").trim();
69821
70102
  if (raw)
69822
70103
  savedHistory = raw.split("\n").reverse();
69823
70104
  }
@@ -69920,12 +70201,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
69920
70201
  if (!line.trim())
69921
70202
  return;
69922
70203
  try {
69923
- mkdirSync29(HISTORY_DIR, { recursive: true });
70204
+ mkdirSync30(HISTORY_DIR, { recursive: true });
69924
70205
  appendFileSync5(HISTORY_FILE, line + "\n", "utf8");
69925
70206
  if (Math.random() < 0.02) {
69926
- const all = readFileSync44(HISTORY_FILE, "utf8").trim().split("\n");
70207
+ const all = readFileSync45(HISTORY_FILE, "utf8").trim().split("\n");
69927
70208
  if (all.length > MAX_HISTORY_LINES) {
69928
- writeFileSync27(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
70209
+ writeFileSync28(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
69929
70210
  }
69930
70211
  }
69931
70212
  } catch {
@@ -70109,7 +70390,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70109
70390
  } catch {
70110
70391
  }
70111
70392
  try {
70112
- const oaDir = join72(repoRoot, ".oa");
70393
+ const oaDir = join73(repoRoot, ".oa");
70113
70394
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
70114
70395
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
70115
70396
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -70141,7 +70422,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70141
70422
  } catch {
70142
70423
  }
70143
70424
  try {
70144
- const oaDir = join72(repoRoot, ".oa");
70425
+ const oaDir = join73(repoRoot, ".oa");
70145
70426
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
70146
70427
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
70147
70428
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -70182,11 +70463,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70182
70463
  }
70183
70464
  try {
70184
70465
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
70185
- const globalNamePath = join72(_hd(), ".open-agents", "agent-name");
70466
+ const globalNamePath = join73(_hd(), ".open-agents", "agent-name");
70186
70467
  let agName = "";
70187
70468
  try {
70188
- if (existsSync55(globalNamePath))
70189
- agName = readFileSync44(globalNamePath, "utf8").trim();
70469
+ if (existsSync56(globalNamePath))
70470
+ agName = readFileSync45(globalNamePath, "utf8").trim();
70190
70471
  } catch {
70191
70472
  }
70192
70473
  if (!agName) {
@@ -71162,7 +71443,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71162
71443
  kind,
71163
71444
  targetUrl,
71164
71445
  authKey,
71165
- stateDir: join72(repoRoot, ".oa"),
71446
+ stateDir: join73(repoRoot, ".oa"),
71166
71447
  passthrough: passthrough ?? false,
71167
71448
  loadbalance: loadbalance ?? false,
71168
71449
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -71208,7 +71489,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71208
71489
  await tunnelGateway.stop();
71209
71490
  tunnelGateway = null;
71210
71491
  }
71211
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join72(repoRoot, ".oa") });
71492
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join73(repoRoot, ".oa") });
71212
71493
  newTunnel.on("stats", (stats) => {
71213
71494
  statusBar.setExposeStatus({
71214
71495
  status: stats.status,
@@ -71297,9 +71578,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71297
71578
  if (!result.success)
71298
71579
  throw new Error(result.error || "Connect failed");
71299
71580
  try {
71300
- const nexusPidFile = join72(repoRoot, ".oa", "nexus", "daemon.pid");
71301
- if (existsSync55(nexusPidFile)) {
71302
- const pid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
71581
+ const nexusPidFile = join73(repoRoot, ".oa", "nexus", "daemon.pid");
71582
+ if (existsSync56(nexusPidFile)) {
71583
+ const pid = parseInt(readFileSync45(nexusPidFile, "utf8").trim(), 10);
71303
71584
  if (pid > 0) {
71304
71585
  registry.register({
71305
71586
  name: "Nexus",
@@ -71495,10 +71776,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71495
71776
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
71496
71777
  }
71497
71778
  try {
71498
- const nexusDir = join72(repoRoot, OA_DIR, "nexus");
71499
- const pidFile = join72(nexusDir, "daemon.pid");
71500
- if (existsSync55(pidFile)) {
71501
- const pid = parseInt(readFileSync44(pidFile, "utf8").trim(), 10);
71779
+ const nexusDir = join73(repoRoot, OA_DIR, "nexus");
71780
+ const pidFile = join73(nexusDir, "daemon.pid");
71781
+ if (existsSync56(pidFile)) {
71782
+ const pid = parseInt(readFileSync45(pidFile, "utf8").trim(), 10);
71502
71783
  if (pid > 0) {
71503
71784
  try {
71504
71785
  if (process.platform === "win32") {
@@ -71520,13 +71801,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71520
71801
  } catch {
71521
71802
  }
71522
71803
  try {
71523
- const voiceDir2 = join72(homedir19(), ".open-agents", "voice");
71804
+ const voiceDir2 = join73(homedir19(), ".open-agents", "voice");
71524
71805
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
71525
71806
  for (const pf of voicePidFiles) {
71526
- const pidPath = join72(voiceDir2, pf);
71527
- if (existsSync55(pidPath)) {
71807
+ const pidPath = join73(voiceDir2, pf);
71808
+ if (existsSync56(pidPath)) {
71528
71809
  try {
71529
- const pid = parseInt(readFileSync44(pidPath, "utf8").trim(), 10);
71810
+ const pid = parseInt(readFileSync45(pidPath, "utf8").trim(), 10);
71530
71811
  if (pid > 0) {
71531
71812
  if (process.platform === "win32") {
71532
71813
  try {
@@ -71550,8 +71831,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71550
71831
  execSync35(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
71551
71832
  } catch {
71552
71833
  }
71553
- const oaPath = join72(repoRoot, OA_DIR);
71554
- if (existsSync55(oaPath)) {
71834
+ const oaPath = join73(repoRoot, OA_DIR);
71835
+ if (existsSync56(oaPath)) {
71555
71836
  let deleted = false;
71556
71837
  for (let attempt = 0; attempt < 3; attempt++) {
71557
71838
  try {
@@ -71634,19 +71915,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71634
71915
  try {
71635
71916
  const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
71636
71917
  if (isPersonaPlexRunning2()) {
71637
- const ppPidFile = join72(homedir19(), ".open-agents", "voice", "personaplex", "daemon.pid");
71638
- const ppPortFile = join72(homedir19(), ".open-agents", "voice", "personaplex", "daemon.port");
71639
- if (existsSync55(ppPidFile)) {
71640
- const ppPid = parseInt(readFileSync44(ppPidFile, "utf8").trim(), 10);
71641
- const ppPort = existsSync55(ppPortFile) ? parseInt(readFileSync44(ppPortFile, "utf8").trim(), 10) : void 0;
71918
+ const ppPidFile = join73(homedir19(), ".open-agents", "voice", "personaplex", "daemon.pid");
71919
+ const ppPortFile = join73(homedir19(), ".open-agents", "voice", "personaplex", "daemon.port");
71920
+ if (existsSync56(ppPidFile)) {
71921
+ const ppPid = parseInt(readFileSync45(ppPidFile, "utf8").trim(), 10);
71922
+ const ppPort = existsSync56(ppPortFile) ? parseInt(readFileSync45(ppPortFile, "utf8").trim(), 10) : void 0;
71642
71923
  if (ppPid > 0 && !registry.daemons.has("PersonaPlex")) {
71643
71924
  registry.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
71644
71925
  }
71645
71926
  }
71646
71927
  }
71647
- const nexusPidFile = join72(repoRoot, ".oa", "nexus", "daemon.pid");
71648
- if (existsSync55(nexusPidFile)) {
71649
- const nPid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
71928
+ const nexusPidFile = join73(repoRoot, ".oa", "nexus", "daemon.pid");
71929
+ if (existsSync56(nexusPidFile)) {
71930
+ const nPid = parseInt(readFileSync45(nexusPidFile, "utf8").trim(), 10);
71650
71931
  if (nPid > 0 && !registry.daemons.has("Nexus")) {
71651
71932
  try {
71652
71933
  process.kill(nPid, 0);
@@ -71988,8 +72269,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
71988
72269
  }
71989
72270
  }
71990
72271
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
71991
- const isImage = isImagePath(cleanPath) && existsSync55(resolve32(repoRoot, cleanPath));
71992
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync55(resolve32(repoRoot, cleanPath));
72272
+ const isImage = isImagePath(cleanPath) && existsSync56(resolve32(repoRoot, cleanPath));
72273
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync56(resolve32(repoRoot, cleanPath));
71993
72274
  if (activeTask) {
71994
72275
  if (activeTask.runner.isPaused) {
71995
72276
  activeTask.runner.resume();
@@ -71998,7 +72279,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
71998
72279
  if (isImage) {
71999
72280
  try {
72000
72281
  const imgPath = resolve32(repoRoot, cleanPath);
72001
- const imgBuffer = readFileSync44(imgPath);
72282
+ const imgBuffer = readFileSync45(imgPath);
72002
72283
  const base64 = imgBuffer.toString("base64");
72003
72284
  const ext = extname11(cleanPath).toLowerCase();
72004
72285
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -72213,7 +72494,7 @@ Summarize or analyze this transcription as appropriate.`;
72213
72494
 
72214
72495
  NEW TASK: ${fullInput}`;
72215
72496
  restoredSessionContext = null;
72216
- } else if (existsSync55(join72(repoRoot, ".oa", "context", "session-diary.md"))) {
72497
+ } else if (existsSync56(join73(repoRoot, ".oa", "context", "session-diary.md"))) {
72217
72498
  taskInput = `[Previous sessions exist \u2014 file_read(".oa/context/session-diary.md") to recall]
72218
72499
 
72219
72500
  ${fullInput}`;
@@ -72530,13 +72811,13 @@ async function runWithTUI(task, config, repoPath) {
72530
72811
  const handle = startTask(task, config, repoRoot);
72531
72812
  await handle.promise;
72532
72813
  try {
72533
- const ikDir = join72(repoRoot, ".oa", "identity");
72534
- const ikFile = join72(ikDir, "self-state.json");
72814
+ const ikDir = join73(repoRoot, ".oa", "identity");
72815
+ const ikFile = join73(ikDir, "self-state.json");
72535
72816
  let ikState;
72536
- if (existsSync55(ikFile)) {
72537
- ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
72817
+ if (existsSync56(ikFile)) {
72818
+ ikState = JSON.parse(readFileSync45(ikFile, "utf8"));
72538
72819
  } else {
72539
- mkdirSync29(ikDir, { recursive: true });
72820
+ mkdirSync30(ikDir, { recursive: true });
72540
72821
  ikState = {
72541
72822
  self_id: `oa-${Date.now().toString(36)}`,
72542
72823
  version: 1,
@@ -72558,7 +72839,7 @@ async function runWithTUI(task, config, repoPath) {
72558
72839
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
72559
72840
  ikState.session_count = (ikState.session_count || 0) + 1;
72560
72841
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
72561
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
72842
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
72562
72843
  } catch (ikErr) {
72563
72844
  }
72564
72845
  try {
@@ -72567,12 +72848,12 @@ async function runWithTUI(task, config, repoPath) {
72567
72848
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
72568
72849
  } catch {
72569
72850
  try {
72570
- const archeDir = join72(repoRoot, ".oa", "arche");
72571
- const archeFile = join72(archeDir, "variants.json");
72851
+ const archeDir = join73(repoRoot, ".oa", "arche");
72852
+ const archeFile = join73(archeDir, "variants.json");
72572
72853
  let variants = [];
72573
72854
  try {
72574
- if (existsSync55(archeFile))
72575
- variants = JSON.parse(readFileSync44(archeFile, "utf8"));
72855
+ if (existsSync56(archeFile))
72856
+ variants = JSON.parse(readFileSync45(archeFile, "utf8"));
72576
72857
  } catch {
72577
72858
  }
72578
72859
  variants.push({
@@ -72587,16 +72868,16 @@ async function runWithTUI(task, config, repoPath) {
72587
72868
  });
72588
72869
  if (variants.length > 50)
72589
72870
  variants = variants.slice(-50);
72590
- mkdirSync29(archeDir, { recursive: true });
72591
- writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
72871
+ mkdirSync30(archeDir, { recursive: true });
72872
+ writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
72592
72873
  } catch {
72593
72874
  }
72594
72875
  }
72595
72876
  try {
72596
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72597
- if (existsSync55(metaFile)) {
72598
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72599
- const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
72877
+ const metaFile = join73(repoRoot, ".oa", "memory", "metabolism", "store.json");
72878
+ if (existsSync56(metaFile)) {
72879
+ const store2 = JSON.parse(readFileSync45(metaFile, "utf8"));
72880
+ const surfaced = store2.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
72600
72881
  let updated = false;
72601
72882
  for (const item of surfaced) {
72602
72883
  item.accessCount = (item.accessCount || 0) + 1;
@@ -72606,7 +72887,7 @@ async function runWithTUI(task, config, repoPath) {
72606
72887
  updated = true;
72607
72888
  }
72608
72889
  if (updated) {
72609
- writeFileSync27(metaFile, JSON.stringify(store, null, 2));
72890
+ writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
72610
72891
  }
72611
72892
  }
72612
72893
  } catch {
@@ -72659,9 +72940,9 @@ Rules:
72659
72940
  try {
72660
72941
  const { initDb: initDb2 } = __require("@open-agents/memory");
72661
72942
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
72662
- const dbDir = join72(repoRoot, ".oa", "memory");
72663
- mkdirSync29(dbDir, { recursive: true });
72664
- const db = initDb2(join72(dbDir, "structured.db"));
72943
+ const dbDir = join73(repoRoot, ".oa", "memory");
72944
+ mkdirSync30(dbDir, { recursive: true });
72945
+ const db = initDb2(join73(dbDir, "structured.db"));
72665
72946
  const memStore = new ProceduralMemoryStore2(db);
72666
72947
  memStore.createWithEmbedding({
72667
72948
  content: content.slice(0, 600),
@@ -72676,15 +72957,15 @@ Rules:
72676
72957
  db.close();
72677
72958
  } catch {
72678
72959
  }
72679
- const metaDir = join72(repoRoot, ".oa", "memory", "metabolism");
72680
- const storeFile = join72(metaDir, "store.json");
72681
- let store = [];
72960
+ const metaDir = join73(repoRoot, ".oa", "memory", "metabolism");
72961
+ const storeFile = join73(metaDir, "store.json");
72962
+ let store2 = [];
72682
72963
  try {
72683
- if (existsSync55(storeFile))
72684
- store = JSON.parse(readFileSync44(storeFile, "utf8"));
72964
+ if (existsSync56(storeFile))
72965
+ store2 = JSON.parse(readFileSync45(storeFile, "utf8"));
72685
72966
  } catch {
72686
72967
  }
72687
- store.push({
72968
+ store2.push({
72688
72969
  id: `mem-traj-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
72689
72970
  type: "procedural",
72690
72971
  content: content.slice(0, 600),
@@ -72695,29 +72976,29 @@ Rules:
72695
72976
  lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString(),
72696
72977
  accessCount: 0
72697
72978
  });
72698
- if (store.length > 100)
72699
- store = store.slice(-100);
72700
- mkdirSync29(metaDir, { recursive: true });
72701
- writeFileSync27(storeFile, JSON.stringify(store, null, 2));
72979
+ if (store2.length > 100)
72980
+ store2 = store2.slice(-100);
72981
+ mkdirSync30(metaDir, { recursive: true });
72982
+ writeFileSync28(storeFile, JSON.stringify(store2, null, 2));
72702
72983
  }
72703
72984
  }
72704
72985
  } catch {
72705
72986
  }
72706
72987
  try {
72707
- const cohereSettingsFile = join72(repoRoot, ".oa", "settings.json");
72988
+ const cohereSettingsFile = join73(repoRoot, ".oa", "settings.json");
72708
72989
  let cohereActive = false;
72709
72990
  try {
72710
- if (existsSync55(cohereSettingsFile)) {
72711
- const settings = JSON.parse(readFileSync44(cohereSettingsFile, "utf8"));
72991
+ if (existsSync56(cohereSettingsFile)) {
72992
+ const settings = JSON.parse(readFileSync45(cohereSettingsFile, "utf8"));
72712
72993
  cohereActive = settings.cohere === true;
72713
72994
  }
72714
72995
  } catch {
72715
72996
  }
72716
72997
  if (cohereActive) {
72717
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72718
- if (existsSync55(metaFile)) {
72719
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72720
- const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
72998
+ const metaFile = join73(repoRoot, ".oa", "memory", "metabolism", "store.json");
72999
+ if (existsSync56(metaFile)) {
73000
+ const store2 = JSON.parse(readFileSync45(metaFile, "utf8"));
73001
+ const latest = store2.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
72721
73002
  if (latest && latest.scores?.confidence >= 0.6) {
72722
73003
  try {
72723
73004
  const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
@@ -72741,34 +73022,34 @@ Rules:
72741
73022
  }
72742
73023
  } catch (err) {
72743
73024
  try {
72744
- const ikFile = join72(repoRoot, ".oa", "identity", "self-state.json");
72745
- if (existsSync55(ikFile)) {
72746
- const ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
73025
+ const ikFile = join73(repoRoot, ".oa", "identity", "self-state.json");
73026
+ if (existsSync56(ikFile)) {
73027
+ const ikState = JSON.parse(readFileSync45(ikFile, "utf8"));
72747
73028
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
72748
73029
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
72749
73030
  ikState.session_count = (ikState.session_count || 0) + 1;
72750
73031
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
72751
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
73032
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
72752
73033
  }
72753
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72754
- if (existsSync55(metaFile)) {
72755
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72756
- const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
73034
+ const metaFile = join73(repoRoot, ".oa", "memory", "metabolism", "store.json");
73035
+ if (existsSync56(metaFile)) {
73036
+ const store2 = JSON.parse(readFileSync45(metaFile, "utf8"));
73037
+ const surfaced = store2.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
72757
73038
  for (const item of surfaced) {
72758
73039
  item.accessCount = (item.accessCount || 0) + 1;
72759
73040
  item.lastAccessedAt = (/* @__PURE__ */ new Date()).toISOString();
72760
73041
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
72761
73042
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
72762
73043
  }
72763
- writeFileSync27(metaFile, JSON.stringify(store, null, 2));
73044
+ writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
72764
73045
  }
72765
73046
  try {
72766
- const archeDir = join72(repoRoot, ".oa", "arche");
72767
- const archeFile = join72(archeDir, "variants.json");
73047
+ const archeDir = join73(repoRoot, ".oa", "arche");
73048
+ const archeFile = join73(archeDir, "variants.json");
72768
73049
  let variants = [];
72769
73050
  try {
72770
- if (existsSync55(archeFile))
72771
- variants = JSON.parse(readFileSync44(archeFile, "utf8"));
73051
+ if (existsSync56(archeFile))
73052
+ variants = JSON.parse(readFileSync45(archeFile, "utf8"));
72772
73053
  } catch {
72773
73054
  }
72774
73055
  variants.push({
@@ -72783,8 +73064,8 @@ Rules:
72783
73064
  });
72784
73065
  if (variants.length > 50)
72785
73066
  variants = variants.slice(-50);
72786
- mkdirSync29(archeDir, { recursive: true });
72787
- writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
73067
+ mkdirSync30(archeDir, { recursive: true });
73068
+ writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
72788
73069
  } catch {
72789
73070
  }
72790
73071
  } catch {
@@ -72854,13 +73135,13 @@ __export(run_exports, {
72854
73135
  });
72855
73136
  import { resolve as resolve33 } from "node:path";
72856
73137
  import { spawn as spawn22 } from "node:child_process";
72857
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync28, readFileSync as readFileSync45, readdirSync as readdirSync23, existsSync as existsSync56 } from "node:fs";
73138
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29, readFileSync as readFileSync46, readdirSync as readdirSync23, existsSync as existsSync57 } from "node:fs";
72858
73139
  import { randomBytes as randomBytes17 } from "node:crypto";
72859
- import { join as join73 } from "node:path";
73140
+ import { join as join74 } from "node:path";
72860
73141
  function jobsDir2(repoPath) {
72861
73142
  const root = resolve33(repoPath ?? process.cwd());
72862
- const dir = join73(root, ".oa", "jobs");
72863
- mkdirSync30(dir, { recursive: true });
73143
+ const dir = join74(root, ".oa", "jobs");
73144
+ mkdirSync31(dir, { recursive: true });
72864
73145
  return dir;
72865
73146
  }
72866
73147
  async function runCommand(opts, config) {
@@ -72945,7 +73226,7 @@ async function runBackground(task, config, opts) {
72945
73226
  });
72946
73227
  child.unref();
72947
73228
  job.pid = child.pid ?? 0;
72948
- writeFileSync28(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
73229
+ writeFileSync29(join74(dir, `${id}.json`), JSON.stringify(job, null, 2));
72949
73230
  let output = "";
72950
73231
  child.stdout?.on("data", (chunk) => {
72951
73232
  output += chunk.toString();
@@ -72961,7 +73242,7 @@ async function runBackground(task, config, opts) {
72961
73242
  job.summary = result.summary;
72962
73243
  job.durationMs = result.durationMs;
72963
73244
  job.error = result.error;
72964
- writeFileSync28(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
73245
+ writeFileSync29(join74(dir, `${id}.json`), JSON.stringify(job, null, 2));
72965
73246
  } catch {
72966
73247
  }
72967
73248
  });
@@ -72977,13 +73258,13 @@ async function runBackground(task, config, opts) {
72977
73258
  }
72978
73259
  function statusCommand(jobId, repoPath) {
72979
73260
  const dir = jobsDir2(repoPath);
72980
- const file = join73(dir, `${jobId}.json`);
72981
- if (!existsSync56(file)) {
73261
+ const file = join74(dir, `${jobId}.json`);
73262
+ if (!existsSync57(file)) {
72982
73263
  console.error(`Job not found: ${jobId}`);
72983
73264
  console.log(`Available jobs: oa jobs`);
72984
73265
  process.exit(1);
72985
73266
  }
72986
- const job = JSON.parse(readFileSync45(file, "utf-8"));
73267
+ const job = JSON.parse(readFileSync46(file, "utf-8"));
72987
73268
  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`;
72988
73269
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
72989
73270
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -73006,7 +73287,7 @@ function jobsCommand(repoPath) {
73006
73287
  console.log("Jobs:");
73007
73288
  for (const file of files) {
73008
73289
  try {
73009
- const job = JSON.parse(readFileSync45(join73(dir, file), "utf-8"));
73290
+ const job = JSON.parse(readFileSync46(join74(dir, file), "utf-8"));
73010
73291
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
73011
73292
  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`;
73012
73293
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -73026,7 +73307,7 @@ import { glob } from "glob";
73026
73307
  import ignore from "ignore";
73027
73308
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
73028
73309
  import { createHash as createHash6 } from "node:crypto";
73029
- import { join as join74, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
73310
+ import { join as join75, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
73030
73311
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
73031
73312
  var init_codebase_indexer = __esm({
73032
73313
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -73070,7 +73351,7 @@ var init_codebase_indexer = __esm({
73070
73351
  const ig = ignore.default();
73071
73352
  if (this.config.respectGitignore) {
73072
73353
  try {
73073
- const gitignoreContent = await readFile23(join74(this.config.rootDir, ".gitignore"), "utf-8");
73354
+ const gitignoreContent = await readFile23(join75(this.config.rootDir, ".gitignore"), "utf-8");
73074
73355
  ig.add(gitignoreContent);
73075
73356
  } catch {
73076
73357
  }
@@ -73085,7 +73366,7 @@ var init_codebase_indexer = __esm({
73085
73366
  for (const relativePath of files) {
73086
73367
  if (ig.ignores(relativePath))
73087
73368
  continue;
73088
- const fullPath = join74(this.config.rootDir, relativePath);
73369
+ const fullPath = join75(this.config.rootDir, relativePath);
73089
73370
  try {
73090
73371
  const fileStat = await stat4(fullPath);
73091
73372
  if (fileStat.size > this.config.maxFileSize)
@@ -73131,7 +73412,7 @@ var init_codebase_indexer = __esm({
73131
73412
  if (!child) {
73132
73413
  child = {
73133
73414
  name: part,
73134
- path: join74(current.path, part),
73415
+ path: join75(current.path, part),
73135
73416
  type: "directory",
73136
73417
  children: []
73137
73418
  };
@@ -73214,13 +73495,13 @@ __export(index_repo_exports, {
73214
73495
  indexRepoCommand: () => indexRepoCommand
73215
73496
  });
73216
73497
  import { resolve as resolve34 } from "node:path";
73217
- import { existsSync as existsSync57, statSync as statSync17 } from "node:fs";
73498
+ import { existsSync as existsSync58, statSync as statSync17 } from "node:fs";
73218
73499
  import { cwd as cwd2 } from "node:process";
73219
73500
  async function indexRepoCommand(opts, _config) {
73220
73501
  const repoRoot = resolve34(opts.repoPath ?? cwd2());
73221
73502
  printHeader("Index Repository");
73222
73503
  printInfo(`Indexing: ${repoRoot}`);
73223
- if (!existsSync57(repoRoot)) {
73504
+ if (!existsSync58(repoRoot)) {
73224
73505
  printError(`Path does not exist: ${repoRoot}`);
73225
73506
  process.exit(1);
73226
73507
  }
@@ -73472,7 +73753,7 @@ var config_exports2 = {};
73472
73753
  __export(config_exports2, {
73473
73754
  configCommand: () => configCommand
73474
73755
  });
73475
- import { join as join75, resolve as resolve35 } from "node:path";
73756
+ import { join as join76, resolve as resolve35 } from "node:path";
73476
73757
  import { homedir as homedir20 } from "node:os";
73477
73758
  import { cwd as cwd3 } from "node:process";
73478
73759
  function redactIfSensitive(key, value) {
@@ -73555,7 +73836,7 @@ function handleShow(opts, config) {
73555
73836
  }
73556
73837
  }
73557
73838
  printSection("Config File");
73558
- printInfo(`~/.open-agents/config.json (${join75(homedir20(), ".open-agents", "config.json")})`);
73839
+ printInfo(`~/.open-agents/config.json (${join76(homedir20(), ".open-agents", "config.json")})`);
73559
73840
  printSection("Priority Chain");
73560
73841
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
73561
73842
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -73594,7 +73875,7 @@ function handleSet(opts, _config) {
73594
73875
  const coerced = coerceForSettings(key, value);
73595
73876
  saveProjectSettings(repoRoot, { [key]: coerced });
73596
73877
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
73597
- printInfo(`Saved to ${join75(repoRoot, ".oa", "settings.json")}`);
73878
+ printInfo(`Saved to ${join76(repoRoot, ".oa", "settings.json")}`);
73598
73879
  printInfo("This override applies only when running in this workspace.");
73599
73880
  } catch (err) {
73600
73881
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -73737,8 +74018,8 @@ __export(eval_exports, {
73737
74018
  evalCommand: () => evalCommand
73738
74019
  });
73739
74020
  import { tmpdir as tmpdir10 } from "node:os";
73740
- import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29 } from "node:fs";
73741
- import { join as join76 } from "node:path";
74021
+ import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30 } from "node:fs";
74022
+ import { join as join77 } from "node:path";
73742
74023
  async function evalCommand(opts, config) {
73743
74024
  const suiteName = opts.suite ?? "basic";
73744
74025
  const suite = SUITES[suiteName];
@@ -73863,9 +74144,9 @@ async function evalCommand(opts, config) {
73863
74144
  process.exit(failed > 0 ? 1 : 0);
73864
74145
  }
73865
74146
  function createTempEvalRepo() {
73866
- const dir = join76(tmpdir10(), `open-agents-eval-${Date.now()}`);
73867
- mkdirSync31(dir, { recursive: true });
73868
- writeFileSync29(join76(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
74147
+ const dir = join77(tmpdir10(), `open-agents-eval-${Date.now()}`);
74148
+ mkdirSync32(dir, { recursive: true });
74149
+ writeFileSync30(join77(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
73869
74150
  return dir;
73870
74151
  }
73871
74152
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -73925,7 +74206,7 @@ init_updater();
73925
74206
  import { parseArgs as nodeParseArgs2 } from "node:util";
73926
74207
  import { createRequire as createRequire5 } from "node:module";
73927
74208
  import { fileURLToPath as fileURLToPath15 } from "node:url";
73928
- import { dirname as dirname23, join as join77 } from "node:path";
74209
+ import { dirname as dirname23, join as join78 } from "node:path";
73929
74210
 
73930
74211
  // packages/cli/dist/cli.js
73931
74212
  import { createInterface } from "node:readline";
@@ -74032,7 +74313,7 @@ init_output();
74032
74313
  function getVersion5() {
74033
74314
  try {
74034
74315
  const require2 = createRequire5(import.meta.url);
74035
- const pkgPath = join77(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
74316
+ const pkgPath = join78(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
74036
74317
  const pkg = require2(pkgPath);
74037
74318
  return pkg.version;
74038
74319
  } catch {
@@ -74307,12 +74588,12 @@ function crashLog(label, err) {
74307
74588
  const logLine = `[${timestamp}] ${label}: ${msg}
74308
74589
  `;
74309
74590
  try {
74310
- const { appendFileSync: appendFileSync6, mkdirSync: mkdirSync32 } = __require("node:fs");
74311
- const { join: join78 } = __require("node:path");
74591
+ const { appendFileSync: appendFileSync6, mkdirSync: mkdirSync33 } = __require("node:fs");
74592
+ const { join: join79 } = __require("node:path");
74312
74593
  const { homedir: homedir21 } = __require("node:os");
74313
- const logDir = join78(homedir21(), ".open-agents");
74314
- mkdirSync32(logDir, { recursive: true });
74315
- appendFileSync6(join78(logDir, "crash.log"), logLine);
74594
+ const logDir = join79(homedir21(), ".open-agents");
74595
+ mkdirSync33(logDir, { recursive: true });
74596
+ appendFileSync6(join79(logDir, "crash.log"), logLine);
74316
74597
  } catch {
74317
74598
  }
74318
74599
  try {