open-agents-ai 0.185.77 → 0.185.79

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 +806 -425
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11957,8 +11957,8 @@ async function loadTranscribeCli() {
11957
11957
  const nvmBase = join19(homedir7(), ".nvm", "versions", "node");
11958
11958
  if (existsSync16(nvmBase)) {
11959
11959
  try {
11960
- const { readdirSync: readdirSync24 } = await import("node:fs");
11961
- for (const ver of readdirSync24(nvmBase)) {
11960
+ const { readdirSync: readdirSync25 } = await import("node:fs");
11961
+ for (const ver of readdirSync25(nvmBase)) {
11962
11962
  const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
11963
11963
  if (existsSync16(join19(tcPath, "dist", "index.js"))) {
11964
11964
  const { createRequire: createRequire6 } = await import("node:module");
@@ -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: readFileSync48, existsSync: existsSync60 } = await import("node:fs");
13824
13824
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13825
- if (!existsSync58(sessionPath))
13825
+ if (!existsSync60(sessionPath))
13826
13826
  return null;
13827
- return JSON.parse(readFileSync46(sessionPath, "utf8"));
13827
+ return JSON.parse(readFileSync48(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");
14005
- const files = readdirSync24(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
14004
+ const { readdirSync: readdirSync25, readFileSync: readFileSync48 } = await import("node:fs");
14005
+ const files = readdirSync25(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 = readFileSync48(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: readFileSync48, existsSync: existsSync60 } = __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 (!existsSync60(storeFile))
14395
14395
  return "";
14396
- let store = [];
14396
+ let store2 = [];
14397
14397
  try {
14398
- store = JSON.parse(readFileSync46(storeFile, "utf8"));
14398
+ store2 = JSON.parse(readFileSync48(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: readFileSync48, writeFileSync: writeFileSync31, existsSync: existsSync60, 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 (!existsSync60(storeFile))
14424
14424
  return;
14425
- let store = [];
14425
+ let store2 = [];
14426
14426
  try {
14427
- store = JSON.parse(readFileSync46(storeFile, "utf8"));
14427
+ store2 = JSON.parse(readFileSync48(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: readFileSync48, existsSync: existsSync60 } = __require("node:fs");
14875
14875
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14876
- if (!existsSync58(archiveFile))
14876
+ if (!existsSync60(archiveFile))
14877
14877
  return "";
14878
14878
  let variants = [];
14879
14879
  try {
14880
- variants = JSON.parse(readFileSync46(archiveFile, "utf8"));
14880
+ variants = JSON.parse(readFileSync48(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: readFileSync48, writeFileSync: writeFileSync31, existsSync: existsSync60, 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 (existsSync60(archiveFile))
14904
+ variants = JSON.parse(readFileSync48(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: join80 } = __require("node:path");
27427
+ const sessionDir = join80(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(join80(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: readFileSync48, unlinkSync: unlinkSync13 } = await import("node:fs");
28579
+ const { join: join80 } = 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 = join80(tmpdir11(), `oa_img_in_${Date.now()}.png`);
28582
+ const tmpOut = join80(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 = readFileSync48(tmpOut);
28589
28589
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
28590
28590
  try {
28591
28591
  unlinkSync13(tmpIn);
@@ -30716,8 +30716,8 @@ var init_listen = __esm({
30716
30716
  const nvmBase = join48(homedir11(), ".nvm", "versions", "node");
30717
30717
  if (existsSync32(nvmBase)) {
30718
30718
  try {
30719
- const { readdirSync: readdirSync24 } = await import("node:fs");
30720
- for (const ver of readdirSync24(nvmBase)) {
30719
+ const { readdirSync: readdirSync25 } = await import("node:fs");
30720
+ for (const ver of readdirSync25(nvmBase)) {
30721
30721
  const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
30722
30722
  if (existsSync32(join48(tcPath, "dist", "index.js"))) {
30723
30723
  const { createRequire: createRequire6 } = await import("node:module");
@@ -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: existsSync60, readFileSync: readFileSync48 } = await import("node:fs");
39561
+ const { join: join80 } = 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 = join80(nexusDir, "status.json");
39568
+ if (existsSync60(statusPath)) {
39569
+ const status = JSON.parse(readFileSync48(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 = join80(nexusDir, "pricing.json");
39577
+ if (existsSync60(pricingPath)) {
39578
39578
  try {
39579
- const pricing = JSON.parse(readFileSync46(pricingPath, "utf8"));
39579
+ const pricing = JSON.parse(readFileSync48(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 = join80(nexusDir, "peer-models-cache.json");
39594
+ if (existsSync60(cachePath)) {
39595
39595
  try {
39596
- const cache4 = JSON.parse(readFileSync46(cachePath, "utf8"));
39596
+ const cache4 = JSON.parse(readFileSync48(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 = join80(nexusDir, "pricing.json");
39712
+ if (existsSync60(pricingPath)) {
39713
39713
  try {
39714
- const pricing = JSON.parse(readFileSync46(pricingPath, "utf8"));
39714
+ const pricing = JSON.parse(readFileSync48(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: join80, dirname: dirname24 } = await import("node:path");
52970
+ const cachePath = join80(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: join80 } = await import("node:path");
53172
+ const { existsSync: existsSync60 } = 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
+ join80(thisDir, "..", "package.json"),
53177
+ join80(thisDir, "..", "..", "package.json"),
53178
+ join80(thisDir, "..", "..", "..", "package.json")
53179
53179
  ];
53180
53180
  for (const pkgPath of candidates) {
53181
- if (existsSync58(pkgPath)) {
53181
+ if (existsSync60(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";
@@ -54151,11 +54151,11 @@ function loadMemoryDir(memDir, scope) {
54151
54151
  return lines.join("\n");
54152
54152
  }
54153
54153
  function loadSessionHistory(repoRoot) {
54154
- const sessions = loadRecentSessions(repoRoot, 5);
54155
- if (sessions.length === 0)
54154
+ const sessions2 = loadRecentSessions(repoRoot, 5);
54155
+ if (sessions2.length === 0)
54156
54156
  return "";
54157
54157
  const lines = ["Recent tasks in this project:"];
54158
- for (const s of sessions) {
54158
+ for (const s of sessions2) {
54159
54159
  if (!s.startedAt || !s.task)
54160
54160
  continue;
54161
54161
  const status = s.completed ? "completed" : "incomplete";
@@ -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("->");
@@ -55490,8 +55490,8 @@ function listBannerDesigns(workDir) {
55490
55490
  if (!existsSync45(dir))
55491
55491
  return [];
55492
55492
  try {
55493
- const { readdirSync: readdirSync24 } = __require("node:fs");
55494
- return readdirSync24(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
55493
+ const { readdirSync: readdirSync25 } = __require("node:fs");
55494
+ return readdirSync25(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
55495
55495
  } catch {
55496
55496
  return [];
55497
55497
  }
@@ -56039,8 +56039,8 @@ function extractFromManifests(repoRoot, tags) {
56039
56039
  }
56040
56040
  function extractFromSessions(repoRoot, tags) {
56041
56041
  try {
56042
- const sessions = loadRecentSessions(repoRoot, 10);
56043
- for (const session of sessions) {
56042
+ const sessions2 = loadRecentSessions(repoRoot, 10);
56043
+ for (const session of sessions2) {
56044
56044
  if (session.task) {
56045
56045
  const words = session.task.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 3 && !STOP_WORDS.has(w));
56046
56046
  tags.push(...words.slice(0, 4));
@@ -65567,8 +65567,16 @@ body {
65567
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
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
65569
  </div>
65570
- <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Endpoint</h3>
65571
- <div id="config-endpoint" style="font-size:0.78rem;color:#888"></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>
65572
65580
  <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Profiles</h3>
65573
65581
  <div id="config-profiles" style="font-size:0.78rem"></div>
65574
65582
  <h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Export Conversation</h3>
@@ -65609,6 +65617,7 @@ const statusEl = document.getElementById('status');
65609
65617
  let apiKey = localStorage.getItem('oa-api-key') || '';
65610
65618
  let streaming = false;
65611
65619
  let messages = [];
65620
+ let chatSessionId = null; // stateful session for /v1/chat
65612
65621
 
65613
65622
  // Auto-resize textarea
65614
65623
  input.addEventListener('input', () => {
@@ -65714,22 +65723,25 @@ async function sendMessage() {
65714
65723
  let fullContent = '';
65715
65724
 
65716
65725
  try {
65726
+ // Use stateful /v1/chat endpoint (maintains OA identity + context)
65717
65727
  const body = {
65728
+ session_id: chatSessionId,
65718
65729
  model: modelSelect.value,
65719
- messages: [
65720
- ...(sysPrompt ? [{ role: 'system', content: sysPrompt }] : []),
65721
- ...messages,
65722
- ],
65730
+ message: text,
65723
65731
  stream: true,
65724
65732
  max_tokens: 4096,
65725
65733
  };
65726
65734
 
65727
- const response = await fetch('/v1/chat/completions', {
65735
+ const response = await fetch('/v1/chat', {
65728
65736
  method: 'POST',
65729
65737
  headers: headers(),
65730
65738
  body: JSON.stringify(body),
65731
65739
  });
65732
65740
 
65741
+ // Capture session ID from response header
65742
+ const sid = response.headers.get('x-session-id');
65743
+ if (sid) chatSessionId = sid;
65744
+
65733
65745
  const reader = response.body.getReader();
65734
65746
  const decoder = new TextDecoder();
65735
65747
  let buffer = '';
@@ -65867,6 +65879,21 @@ async function loadConfig() {
65867
65879
  } catch {}
65868
65880
  }
65869
65881
 
65882
+ async function switchEndpoint() {
65883
+ const url = document.getElementById('config-ep-url').value.trim();
65884
+ const auth = document.getElementById('config-ep-key').value.trim();
65885
+ const backendType = document.getElementById('config-ep-type').value;
65886
+ if (!url) return;
65887
+ try {
65888
+ await fetch('/v1/config/endpoint', {
65889
+ method: 'PUT', headers: headers(),
65890
+ body: JSON.stringify({ url, auth: auth ? 'Bearer ' + auth : '', backendType }),
65891
+ });
65892
+ loadConfig();
65893
+ loadModels(); // refresh model list from new endpoint
65894
+ } catch {}
65895
+ }
65896
+
65870
65897
  async function switchModel() {
65871
65898
  const model = document.getElementById('config-model-select').value;
65872
65899
  if (!model) return;
@@ -66038,19 +66065,39 @@ async function loadDashboard() {
66038
66065
  '<div style="color:#555;font-size:0.6rem">VERSION</div>' +
66039
66066
  '<div style="color:#b0b0b0;font-size:0.8rem">' + d.version + '</div></div>';
66040
66067
  } catch {}
66041
- // Usage
66068
+ // Usage \u2014 per-provider breakdown with persistent totals
66042
66069
  try {
66043
66070
  const r = await fetch('/v1/usage', { headers: headers() });
66044
66071
  const d = await r.json();
66072
+ const ps = d.persistent?.byProvider || {};
66073
+ let providerCards = '';
66074
+ for (const [label, stats] of Object.entries(ps)) {
66075
+ const s = stats;
66076
+ providerCards +=
66077
+ '<div style="background:#1e1e22;border-left:2px solid #b2920a;padding:8px 12px;margin:4px 0">' +
66078
+ '<div style="color:#b2920a;font-size:0.7rem;font-weight:bold">' + label + '</div>' +
66079
+ '<div style="display:flex;gap:16px;margin-top:4px">' +
66080
+ '<span style="color:#555;font-size:0.65rem">in: <span style="color:#b0b0b0">' + (s.tokensIn || 0).toLocaleString() + '</span></span>' +
66081
+ '<span style="color:#555;font-size:0.65rem">out: <span style="color:#b0b0b0">' + (s.tokensOut || 0).toLocaleString() + '</span></span>' +
66082
+ '<span style="color:#555;font-size:0.65rem">reqs: <span style="color:#b0b0b0">' + (s.requests || 0).toLocaleString() + '</span></span>' +
66083
+ '</div></div>';
66084
+ }
66085
+ const totalIn = d.persistent?.totalIn || d.totalTokensIn || 0;
66086
+ const totalOut = d.persistent?.totalOut || d.totalTokensOut || 0;
66045
66087
  document.getElementById('dashboard-usage').innerHTML =
66046
- '<div style="display:flex;gap:12px;flex-wrap:wrap">' +
66088
+ '<h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:8px">Token Usage by Provider (persistent)</h3>' +
66089
+ '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:8px">' +
66047
66090
  '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
66048
- '<div style="color:#555;font-size:0.6rem">TOKENS IN</div>' +
66049
- '<div style="color:#b2920a;font-size:0.8rem">' + (d.totalTokensIn || 0).toLocaleString() + '</div></div>' +
66091
+ '<div style="color:#555;font-size:0.6rem">TOTAL IN</div>' +
66092
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalIn.toLocaleString() + '</div></div>' +
66050
66093
  '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
66051
- '<div style="color:#555;font-size:0.6rem">TOKENS OUT</div>' +
66052
- '<div style="color:#b2920a;font-size:0.8rem">' + (d.totalTokensOut || 0).toLocaleString() + '</div></div>' +
66053
- '</div>';
66094
+ '<div style="color:#555;font-size:0.6rem">TOTAL OUT</div>' +
66095
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalOut.toLocaleString() + '</div></div>' +
66096
+ '<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
66097
+ '<div style="color:#555;font-size:0.6rem">TOTAL REQUESTS</div>' +
66098
+ '<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + (d.persistent?.totalRequests || 0).toLocaleString() + '</div></div>' +
66099
+ '</div>' +
66100
+ (providerCards || '<div style="color:#555;font-size:0.7rem">No provider usage recorded yet</div>');
66054
66101
  } catch {}
66055
66102
  }
66056
66103
 
@@ -66216,25 +66263,222 @@ var init_auth_oidc = __esm({
66216
66263
  }
66217
66264
  });
66218
66265
 
66219
- // packages/cli/dist/api/profiles.js
66220
- import { existsSync as existsSync53, readFileSync as readFileSync42, writeFileSync as writeFileSync25, mkdirSync as mkdirSync27, readdirSync as readdirSync20, unlinkSync as unlinkSync12 } from "node:fs";
66266
+ // packages/cli/dist/api/chat-session.js
66267
+ import { randomUUID as randomUUID4 } from "node:crypto";
66268
+ import { existsSync as existsSync53, readFileSync as readFileSync42, readdirSync as readdirSync20 } from "node:fs";
66221
66269
  import { join as join70 } from "node:path";
66270
+ function buildSystemPrompt(cwd4) {
66271
+ const parts = [];
66272
+ parts.push("You are Open Agent (OA), an AI coding assistant running locally via Ollama. You have access to the user's workspace and can discuss code, files, and projects. Be helpful, concise, and technically precise. When asked about files or code, describe what you know from the conversation context.");
66273
+ parts.push(`\\nEnvironment: ${process.platform}, Node ${process.version}, CWD: ${cwd4}`);
66274
+ const diaryPath = join70(cwd4, ".oa", "context", "session-diary.md");
66275
+ if (existsSync53(diaryPath)) {
66276
+ try {
66277
+ const diary = readFileSync42(diaryPath, "utf-8").slice(0, 1e3);
66278
+ parts.push(`\\nPrevious session history:\\n${diary}`);
66279
+ } catch {
66280
+ }
66281
+ }
66282
+ const memDir = join70(cwd4, ".oa", "memory");
66283
+ if (existsSync53(memDir)) {
66284
+ try {
66285
+ const files = readdirSync20(memDir).filter((f) => f.endsWith(".json")).slice(0, 5);
66286
+ if (files.length > 0) {
66287
+ parts.push("\\nPersistent memory topics: " + files.map((f) => f.replace(".json", "")).join(", "));
66288
+ for (const f of files.slice(0, 3)) {
66289
+ try {
66290
+ const data = JSON.parse(readFileSync42(join70(memDir, f), "utf-8"));
66291
+ const entries = Object.entries(data).slice(0, 3);
66292
+ if (entries.length > 0) {
66293
+ parts.push(`\\nMemory [${f.replace(".json", "")}]: ` + entries.map(([k, v]) => `${k}: ${String(v.value ?? v).slice(0, 100)}`).join("; "));
66294
+ }
66295
+ } catch {
66296
+ }
66297
+ }
66298
+ }
66299
+ } catch {
66300
+ }
66301
+ }
66302
+ for (const name of ["AGENTS.md", "OA.md", ".open-agents.md"]) {
66303
+ const p = join70(cwd4, name);
66304
+ if (existsSync53(p)) {
66305
+ try {
66306
+ const content = readFileSync42(p, "utf-8").slice(0, 500);
66307
+ parts.push(`\\nProject instructions (${name}):\\n${content}`);
66308
+ } catch {
66309
+ }
66310
+ }
66311
+ }
66312
+ return parts.join("");
66313
+ }
66314
+ function getSession(sessionId, model, cwd4) {
66315
+ if (sessionId && sessions.has(sessionId)) {
66316
+ const s = sessions.get(sessionId);
66317
+ s.lastActivity = Date.now();
66318
+ return s;
66319
+ }
66320
+ const id = sessionId || randomUUID4();
66321
+ const systemPrompt = buildSystemPrompt(cwd4);
66322
+ const session = {
66323
+ id,
66324
+ messages: [{ role: "system", content: systemPrompt }],
66325
+ model,
66326
+ createdAt: Date.now(),
66327
+ lastActivity: Date.now(),
66328
+ tokensIn: 0,
66329
+ tokensOut: 0
66330
+ };
66331
+ sessions.set(id, session);
66332
+ return session;
66333
+ }
66334
+ function addUserMessage(session, content) {
66335
+ session.messages.push({ role: "user", content });
66336
+ session.lastActivity = Date.now();
66337
+ return [...session.messages];
66338
+ }
66339
+ function addAssistantMessage(session, content) {
66340
+ session.messages.push({ role: "assistant", content });
66341
+ session.lastActivity = Date.now();
66342
+ }
66343
+ function trackSessionTokens(session, tokensIn, tokensOut) {
66344
+ session.tokensIn += tokensIn;
66345
+ session.tokensOut += tokensOut;
66346
+ }
66347
+ function listSessions() {
66348
+ return Array.from(sessions.values()).map((s) => ({
66349
+ id: s.id,
66350
+ model: s.model,
66351
+ messages: s.messages.length - 1,
66352
+ // exclude system prompt
66353
+ tokensIn: s.tokensIn,
66354
+ tokensOut: s.tokensOut,
66355
+ lastActivity: new Date(s.lastActivity).toISOString()
66356
+ }));
66357
+ }
66358
+ function compactSession(session, maxMessages = 40) {
66359
+ if (session.messages.length <= maxMessages)
66360
+ return;
66361
+ const system = session.messages[0];
66362
+ const recent = session.messages.slice(-20);
66363
+ const middle = session.messages.slice(1, -20);
66364
+ const summary = `[Earlier conversation: ${middle.length} messages discussed ` + middle.filter((m) => m.role === "user").map((m) => m.content.slice(0, 50)).slice(0, 5).join(", ") + "...]";
66365
+ session.messages = [
66366
+ system,
66367
+ { role: "system", content: summary },
66368
+ ...recent
66369
+ ];
66370
+ }
66371
+ var sessions, SESSION_TTL_MS;
66372
+ var init_chat_session = __esm({
66373
+ "packages/cli/dist/api/chat-session.js"() {
66374
+ "use strict";
66375
+ sessions = /* @__PURE__ */ new Map();
66376
+ SESSION_TTL_MS = 30 * 60 * 1e3;
66377
+ setInterval(() => {
66378
+ const now = Date.now();
66379
+ for (const [id, s] of sessions) {
66380
+ if (now - s.lastActivity > SESSION_TTL_MS)
66381
+ sessions.delete(id);
66382
+ }
66383
+ }, 5 * 60 * 1e3);
66384
+ }
66385
+ });
66386
+
66387
+ // packages/cli/dist/api/usage-tracker.js
66388
+ import { mkdirSync as mkdirSync27, readFileSync as readFileSync43, writeFileSync as writeFileSync25, existsSync as existsSync54 } from "node:fs";
66389
+ import { join as join71 } from "node:path";
66390
+ function initUsageTracker(oaDir) {
66391
+ const dir = join71(oaDir, "usage");
66392
+ mkdirSync27(dir, { recursive: true });
66393
+ usageFile = join71(dir, "token-usage.json");
66394
+ try {
66395
+ if (existsSync54(usageFile)) {
66396
+ store = JSON.parse(readFileSync43(usageFile, "utf-8"));
66397
+ }
66398
+ } catch {
66399
+ store = { providers: {}, lastSaved: "" };
66400
+ }
66401
+ initialized2 = true;
66402
+ setInterval(() => {
66403
+ if (dirty)
66404
+ flush();
66405
+ }, 3e4);
66406
+ }
66407
+ function ensureProvider(label) {
66408
+ if (!store.providers[label]) {
66409
+ store.providers[label] = { tokensIn: 0, tokensOut: 0, requests: 0, byDay: {} };
66410
+ }
66411
+ return store.providers[label];
66412
+ }
66413
+ function today() {
66414
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66415
+ }
66416
+ function trackTokens(provider, tokensIn, tokensOut) {
66417
+ if (!initialized2)
66418
+ return;
66419
+ const p = ensureProvider(provider);
66420
+ p.tokensIn += tokensIn;
66421
+ p.tokensOut += tokensOut;
66422
+ p.requests++;
66423
+ const day = today();
66424
+ if (!p.byDay[day])
66425
+ p.byDay[day] = { in: 0, out: 0, reqs: 0 };
66426
+ p.byDay[day].in += tokensIn;
66427
+ p.byDay[day].out += tokensOut;
66428
+ p.byDay[day].reqs++;
66429
+ dirty = true;
66430
+ }
66431
+ function flush() {
66432
+ if (!initialized2 || !dirty)
66433
+ return;
66434
+ try {
66435
+ store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
66436
+ writeFileSync25(usageFile, JSON.stringify(store, null, 2), "utf-8");
66437
+ dirty = false;
66438
+ } catch {
66439
+ }
66440
+ }
66441
+ function getUsageSummary() {
66442
+ let totalIn = 0, totalOut = 0, totalRequests = 0;
66443
+ const byProvider = {};
66444
+ for (const [label, p] of Object.entries(store.providers)) {
66445
+ totalIn += p.tokensIn;
66446
+ totalOut += p.tokensOut;
66447
+ totalRequests += p.requests;
66448
+ byProvider[label] = { tokensIn: p.tokensIn, tokensOut: p.tokensOut, requests: p.requests };
66449
+ }
66450
+ return { totalIn, totalOut, totalRequests, byProvider };
66451
+ }
66452
+ var store, usageFile, dirty, initialized2;
66453
+ var init_usage_tracker = __esm({
66454
+ "packages/cli/dist/api/usage-tracker.js"() {
66455
+ "use strict";
66456
+ store = { providers: {}, lastSaved: "" };
66457
+ usageFile = "";
66458
+ dirty = false;
66459
+ initialized2 = false;
66460
+ }
66461
+ });
66462
+
66463
+ // packages/cli/dist/api/profiles.js
66464
+ import { existsSync as existsSync55, readFileSync as readFileSync44, writeFileSync as writeFileSync26, mkdirSync as mkdirSync28, readdirSync as readdirSync21, unlinkSync as unlinkSync12 } from "node:fs";
66465
+ import { join as join72 } from "node:path";
66222
66466
  import { homedir as homedir18 } from "node:os";
66223
66467
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
66224
66468
  function globalProfileDir() {
66225
- return join70(homedir18(), ".open-agents", "profiles");
66469
+ return join72(homedir18(), ".open-agents", "profiles");
66226
66470
  }
66227
66471
  function projectProfileDir(projectDir) {
66228
- return join70(projectDir || process.cwd(), ".oa", "profiles");
66472
+ return join72(projectDir || process.cwd(), ".oa", "profiles");
66229
66473
  }
66230
66474
  function listProfiles(projectDir) {
66231
66475
  const result = [];
66232
66476
  const seen = /* @__PURE__ */ new Set();
66233
66477
  const projDir = projectProfileDir(projectDir);
66234
- if (existsSync53(projDir)) {
66235
- for (const f of readdirSync20(projDir).filter((f2) => f2.endsWith(".json"))) {
66478
+ if (existsSync55(projDir)) {
66479
+ for (const f of readdirSync21(projDir).filter((f2) => f2.endsWith(".json"))) {
66236
66480
  try {
66237
- const raw = JSON.parse(readFileSync42(join70(projDir, f), "utf8"));
66481
+ const raw = JSON.parse(readFileSync44(join72(projDir, f), "utf8"));
66238
66482
  const name = f.replace(".json", "");
66239
66483
  seen.add(name);
66240
66484
  result.push({
@@ -66248,13 +66492,13 @@ function listProfiles(projectDir) {
66248
66492
  }
66249
66493
  }
66250
66494
  const globDir = globalProfileDir();
66251
- if (existsSync53(globDir)) {
66252
- for (const f of readdirSync20(globDir).filter((f2) => f2.endsWith(".json"))) {
66495
+ if (existsSync55(globDir)) {
66496
+ for (const f of readdirSync21(globDir).filter((f2) => f2.endsWith(".json"))) {
66253
66497
  const name = f.replace(".json", "");
66254
66498
  if (seen.has(name))
66255
66499
  continue;
66256
66500
  try {
66257
- const raw = JSON.parse(readFileSync42(join70(globDir, f), "utf8"));
66501
+ const raw = JSON.parse(readFileSync44(join72(globDir, f), "utf8"));
66258
66502
  result.push({
66259
66503
  name,
66260
66504
  description: raw.description || "",
@@ -66269,12 +66513,12 @@ function listProfiles(projectDir) {
66269
66513
  }
66270
66514
  function loadProfile(name, password, projectDir) {
66271
66515
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
66272
- const projPath = join70(projectProfileDir(projectDir), `${sanitized}.json`);
66273
- const globPath = join70(globalProfileDir(), `${sanitized}.json`);
66274
- const filePath = existsSync53(projPath) ? projPath : existsSync53(globPath) ? globPath : null;
66516
+ const projPath = join72(projectProfileDir(projectDir), `${sanitized}.json`);
66517
+ const globPath = join72(globalProfileDir(), `${sanitized}.json`);
66518
+ const filePath = existsSync55(projPath) ? projPath : existsSync55(globPath) ? globPath : null;
66275
66519
  if (!filePath)
66276
66520
  return null;
66277
- const raw = JSON.parse(readFileSync42(filePath, "utf8"));
66521
+ const raw = JSON.parse(readFileSync44(filePath, "utf8"));
66278
66522
  if (raw.encrypted === true) {
66279
66523
  if (!password)
66280
66524
  return null;
@@ -66284,23 +66528,23 @@ function loadProfile(name, password, projectDir) {
66284
66528
  }
66285
66529
  function saveProfile(profile, password, scope = "global", projectDir) {
66286
66530
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
66287
- mkdirSync27(dir, { recursive: true });
66531
+ mkdirSync28(dir, { recursive: true });
66288
66532
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
66289
- const filePath = join70(dir, `${sanitized}.json`);
66533
+ const filePath = join72(dir, `${sanitized}.json`);
66290
66534
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
66291
66535
  if (password) {
66292
66536
  const encrypted = encryptProfile(profile, password);
66293
- writeFileSync25(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
66537
+ writeFileSync26(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
66294
66538
  } else {
66295
66539
  profile.encrypted = false;
66296
- writeFileSync25(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
66540
+ writeFileSync26(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
66297
66541
  }
66298
66542
  }
66299
66543
  function deleteProfile(name, scope = "global", projectDir) {
66300
66544
  const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
66301
66545
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
66302
- const filePath = join70(dir, `${sanitized}.json`);
66303
- if (existsSync53(filePath)) {
66546
+ const filePath = join72(dir, `${sanitized}.json`);
66547
+ if (existsSync55(filePath)) {
66304
66548
  unlinkSync12(filePath);
66305
66549
  return true;
66306
66550
  }
@@ -66393,22 +66637,22 @@ import * as http from "node:http";
66393
66637
  import * as https from "node:https";
66394
66638
  import { createRequire as createRequire3 } from "node:module";
66395
66639
  import { fileURLToPath as fileURLToPath13 } from "node:url";
66396
- import { dirname as dirname21, join as join71, resolve as resolve31 } from "node:path";
66640
+ import { dirname as dirname21, join as join73, resolve as resolve31 } from "node:path";
66397
66641
  import { spawn as spawn21 } from "node:child_process";
66398
- import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync26, readFileSync as readFileSync43, readdirSync as readdirSync21, existsSync as existsSync54 } from "node:fs";
66399
- import { randomBytes as randomBytes16, randomUUID as randomUUID4 } from "node:crypto";
66642
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync27, readFileSync as readFileSync45, readdirSync as readdirSync22, existsSync as existsSync56 } from "node:fs";
66643
+ import { randomBytes as randomBytes16, randomUUID as randomUUID5 } from "node:crypto";
66400
66644
  function getVersion3() {
66401
66645
  try {
66402
66646
  const require2 = createRequire3(import.meta.url);
66403
66647
  const thisDir = dirname21(fileURLToPath13(import.meta.url));
66404
66648
  const candidates = [
66405
- join71(thisDir, "..", "package.json"),
66406
- join71(thisDir, "..", "..", "package.json"),
66407
- join71(thisDir, "..", "..", "..", "package.json")
66649
+ join73(thisDir, "..", "package.json"),
66650
+ join73(thisDir, "..", "..", "package.json"),
66651
+ join73(thisDir, "..", "..", "..", "package.json")
66408
66652
  ];
66409
66653
  for (const pkgPath of candidates) {
66410
66654
  try {
66411
- if (!existsSync54(pkgPath))
66655
+ if (!existsSync56(pkgPath))
66412
66656
  continue;
66413
66657
  const pkg = require2(pkgPath);
66414
66658
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
@@ -66424,14 +66668,14 @@ function getVersion3() {
66424
66668
  }
66425
66669
  function getEndpointUsage(label) {
66426
66670
  let u = endpointUsage.get(label);
66427
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66671
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66428
66672
  if (!u) {
66429
- u = { requestTimestamps: [], tokensToday: 0, tokenDate: today };
66673
+ u = { requestTimestamps: [], tokensToday: 0, tokenDate: today2 };
66430
66674
  endpointUsage.set(label, u);
66431
66675
  }
66432
- if (u.tokenDate !== today) {
66676
+ if (u.tokenDate !== today2) {
66433
66677
  u.tokensToday = 0;
66434
- u.tokenDate = today;
66678
+ u.tokenDate = today2;
66435
66679
  }
66436
66680
  return u;
66437
66681
  }
@@ -66709,29 +66953,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
66709
66953
  }
66710
66954
  function jobsDir() {
66711
66955
  const root = resolve31(process.cwd());
66712
- const dir = join71(root, ".oa", "jobs");
66713
- mkdirSync28(dir, { recursive: true });
66956
+ const dir = join73(root, ".oa", "jobs");
66957
+ mkdirSync29(dir, { recursive: true });
66714
66958
  return dir;
66715
66959
  }
66716
66960
  function loadJob(id) {
66717
- const file = join71(jobsDir(), `${id}.json`);
66718
- if (!existsSync54(file))
66961
+ const file = join73(jobsDir(), `${id}.json`);
66962
+ if (!existsSync56(file))
66719
66963
  return null;
66720
66964
  try {
66721
- return JSON.parse(readFileSync43(file, "utf-8"));
66965
+ return JSON.parse(readFileSync45(file, "utf-8"));
66722
66966
  } catch {
66723
66967
  return null;
66724
66968
  }
66725
66969
  }
66726
66970
  function listJobs() {
66727
66971
  const dir = jobsDir();
66728
- if (!existsSync54(dir))
66972
+ if (!existsSync56(dir))
66729
66973
  return [];
66730
- const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).sort();
66974
+ const files = readdirSync22(dir).filter((f) => f.endsWith(".json")).sort();
66731
66975
  const jobs = [];
66732
66976
  for (const file of files) {
66733
66977
  try {
66734
- jobs.push(JSON.parse(readFileSync43(join71(dir, file), "utf-8")));
66978
+ jobs.push(JSON.parse(readFileSync45(join73(dir, file), "utf-8")));
66735
66979
  } catch {
66736
66980
  }
66737
66981
  }
@@ -66742,10 +66986,10 @@ function getKeyUsage(user) {
66742
66986
  perKeyUsage.set(user, { requestTimestamps: [], tokensToday: 0, tokenDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), activeJobs: 0 });
66743
66987
  }
66744
66988
  const u = perKeyUsage.get(user);
66745
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66746
- if (u.tokenDate !== today) {
66989
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
66990
+ if (u.tokenDate !== today2) {
66747
66991
  u.tokensToday = 0;
66748
- u.tokenDate = today;
66992
+ u.tokenDate = today2;
66749
66993
  }
66750
66994
  return u;
66751
66995
  }
@@ -66924,8 +67168,11 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66924
67168
  const parsed = JSON.parse(result.body);
66925
67169
  if (parsed.usage) {
66926
67170
  const totalTok = (parsed.usage.prompt_tokens ?? 0) + (parsed.usage.completion_tokens ?? 0);
66927
- metrics.totalTokensIn += parsed.usage.prompt_tokens ?? 0;
66928
- metrics.totalTokensOut += parsed.usage.completion_tokens ?? 0;
67171
+ const _pIn = parsed.usage.prompt_tokens ?? 0;
67172
+ const _pOut = parsed.usage.completion_tokens ?? 0;
67173
+ metrics.totalTokensIn += _pIn;
67174
+ metrics.totalTokensOut += _pOut;
67175
+ trackTokens(route?.endpoint?.label ?? "local", _pIn, _pOut);
66929
67176
  if (route?.endpoint)
66930
67177
  recordEndpointUsage(route.endpoint.label, totalTok);
66931
67178
  }
@@ -66963,6 +67210,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
66963
67210
  metrics.totalTokensOut += ollamaChunk.eval_count;
66964
67211
  if (ollamaChunk.prompt_eval_count)
66965
67212
  metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
67213
+ trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
66966
67214
  const doneEvent = {
66967
67215
  id: chatId,
66968
67216
  object: "chat.completion.chunk",
@@ -67013,6 +67261,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
67013
67261
  metrics.totalTokensOut += ollamaChunk.eval_count;
67014
67262
  if (ollamaChunk.prompt_eval_count)
67015
67263
  metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
67264
+ trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
67016
67265
  res.write(`data: ${JSON.stringify({
67017
67266
  id: chatId,
67018
67267
  object: "chat.completion.chunk",
@@ -67052,6 +67301,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
67052
67301
  metrics.totalTokensOut += ollamaResp.eval_count;
67053
67302
  if (ollamaResp.prompt_eval_count)
67054
67303
  metrics.totalTokensIn += ollamaResp.prompt_eval_count;
67304
+ trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
67055
67305
  const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
67056
67306
  const openaiResponse = {
67057
67307
  id: chatId,
@@ -67173,8 +67423,8 @@ async function handleV1Run(req, res) {
67173
67423
  if (workingDir) {
67174
67424
  cwd4 = resolve31(workingDir);
67175
67425
  } else if (isolate) {
67176
- const wsDir = join71(dir, "..", "workspaces", id);
67177
- mkdirSync28(wsDir, { recursive: true });
67426
+ const wsDir = join73(dir, "..", "workspaces", id);
67427
+ mkdirSync29(wsDir, { recursive: true });
67178
67428
  cwd4 = wsDir;
67179
67429
  } else {
67180
67430
  cwd4 = resolve31(process.cwd());
@@ -67246,7 +67496,7 @@ async function handleV1Run(req, res) {
67246
67496
  });
67247
67497
  child.unref();
67248
67498
  job.pid = child.pid ?? 0;
67249
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67499
+ writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
67250
67500
  runningProcesses.set(id, child);
67251
67501
  if (streamMode) {
67252
67502
  res.writeHead(200, {
@@ -67273,7 +67523,7 @@ async function handleV1Run(req, res) {
67273
67523
  job.status = code === 0 ? "completed" : "failed";
67274
67524
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
67275
67525
  try {
67276
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67526
+ writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
67277
67527
  } catch {
67278
67528
  }
67279
67529
  runningProcesses.delete(id);
@@ -67304,7 +67554,7 @@ async function handleV1Run(req, res) {
67304
67554
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
67305
67555
  }
67306
67556
  try {
67307
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67557
+ writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
67308
67558
  } catch {
67309
67559
  }
67310
67560
  runningProcesses.delete(id);
@@ -67353,7 +67603,7 @@ function handleV1RunsDelete(res, id) {
67353
67603
  job.error = "Aborted via API";
67354
67604
  const dir = jobsDir();
67355
67605
  try {
67356
- writeFileSync26(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
67606
+ writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
67357
67607
  } catch {
67358
67608
  }
67359
67609
  runningProcesses.delete(id);
@@ -67498,7 +67748,7 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67498
67748
  const urlObj = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
67499
67749
  const pathname = urlObj.pathname;
67500
67750
  const startMs = performance.now();
67501
- const requestId = req.headers["x-request-id"] || randomUUID4();
67751
+ const requestId = req.headers["x-request-id"] || randomUUID5();
67502
67752
  res.setHeader("X-Request-ID", requestId);
67503
67753
  if (method === "OPTIONS") {
67504
67754
  if (!corsHeaders(req, res))
@@ -67573,6 +67823,127 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67573
67823
  return;
67574
67824
  }
67575
67825
  }
67826
+ if (pathname === "/v1/chat" && method === "POST") {
67827
+ if (!checkAuth(req, res, "run")) {
67828
+ status = 401;
67829
+ return;
67830
+ }
67831
+ const chatBody = await parseJsonBody(req);
67832
+ if (!chatBody?.message || typeof chatBody.message !== "string") {
67833
+ jsonResponse(res, 400, { error: "Missing required field: message" });
67834
+ return;
67835
+ }
67836
+ const sessionId = chatBody.session_id;
67837
+ const model = chatBody.model || loadConfig().model;
67838
+ const session = getSession(sessionId, model, resolve31(process.cwd()));
67839
+ const messages = addUserMessage(session, chatBody.message);
67840
+ compactSession(session);
67841
+ const streamMode = chatBody.stream !== false;
67842
+ const chatRequest = {
67843
+ model: session.model,
67844
+ messages,
67845
+ stream: streamMode,
67846
+ max_tokens: chatBody.max_tokens || 4096
67847
+ };
67848
+ const route = resolveModelEndpoint(session.model);
67849
+ const targetUrl = route?.endpoint?.url || loadConfig().backendUrl;
67850
+ if (streamMode) {
67851
+ res.writeHead(200, {
67852
+ "Content-Type": "text/event-stream",
67853
+ "Cache-Control": "no-cache",
67854
+ "Connection": "keep-alive",
67855
+ "X-Session-ID": session.id
67856
+ });
67857
+ let fullContent = "";
67858
+ try {
67859
+ const url = new URL("/api/chat", targetUrl);
67860
+ const isHttps = url.protocol === "https:";
67861
+ const transport = isHttps ? https : http;
67862
+ const reqBody = JSON.stringify({
67863
+ model: session.model.replace(/^local\//, ""),
67864
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
67865
+ stream: true
67866
+ });
67867
+ await new Promise((resolve36, reject) => {
67868
+ const proxyReq = transport.request({
67869
+ hostname: url.hostname,
67870
+ port: url.port || (isHttps ? 443 : 80),
67871
+ path: url.pathname,
67872
+ method: "POST",
67873
+ headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(reqBody) }
67874
+ }, (proxyRes) => {
67875
+ let buffer = "";
67876
+ proxyRes.on("data", (chunk) => {
67877
+ buffer += chunk.toString();
67878
+ const lines = buffer.split("\n");
67879
+ buffer = lines.pop() || "";
67880
+ for (const line of lines) {
67881
+ if (!line.trim())
67882
+ continue;
67883
+ try {
67884
+ const parsed = JSON.parse(line);
67885
+ if (parsed.message?.content) {
67886
+ fullContent += parsed.message.content;
67887
+ const sseChunk = {
67888
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
67889
+ object: "chat.completion.chunk",
67890
+ choices: [{ index: 0, delta: { content: parsed.message.content }, finish_reason: null }]
67891
+ };
67892
+ res.write("data: " + JSON.stringify(sseChunk) + "\n\n");
67893
+ }
67894
+ if (parsed.done) {
67895
+ trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67896
+ trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67897
+ metrics.totalTokensIn += parsed.prompt_eval_count ?? 0;
67898
+ metrics.totalTokensOut += parsed.eval_count ?? 0;
67899
+ res.write("data: [DONE]\n\n");
67900
+ }
67901
+ } catch {
67902
+ }
67903
+ }
67904
+ });
67905
+ proxyRes.on("end", resolve36);
67906
+ proxyRes.on("error", reject);
67907
+ });
67908
+ proxyReq.setTimeout(12e4, () => proxyReq.destroy(new Error("Chat stream timeout")));
67909
+ proxyReq.on("error", reject);
67910
+ proxyReq.write(reqBody);
67911
+ proxyReq.end();
67912
+ });
67913
+ } catch (e) {
67914
+ res.write("data: " + JSON.stringify({ error: e.message }) + "\n\n");
67915
+ }
67916
+ addAssistantMessage(session, fullContent);
67917
+ res.end();
67918
+ } else {
67919
+ try {
67920
+ const result = await ollamaRequest(targetUrl, "/api/chat", "POST", JSON.stringify({
67921
+ model: session.model.replace(/^local\//, ""),
67922
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
67923
+ stream: false
67924
+ }));
67925
+ const parsed = JSON.parse(result.body);
67926
+ const content = parsed.message?.content ?? "";
67927
+ addAssistantMessage(session, content);
67928
+ trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67929
+ trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67930
+ jsonResponse(res, 200, {
67931
+ session_id: session.id,
67932
+ message: { role: "assistant", content },
67933
+ usage: { prompt_tokens: parsed.prompt_eval_count ?? 0, completion_tokens: parsed.eval_count ?? 0 }
67934
+ });
67935
+ } catch (e) {
67936
+ jsonResponse(res, 500, { error: "Chat failed", message: e.message });
67937
+ }
67938
+ }
67939
+ return;
67940
+ }
67941
+ if (pathname === "/v1/chat/sessions" && method === "GET") {
67942
+ if (!checkAuth(req, res, "read"))
67943
+ return;
67944
+ jsonResponse(res, 200, { sessions: listSessions() });
67945
+ return;
67946
+ }
67576
67947
  if (pathname === "/v1/models" && method === "GET") {
67577
67948
  await handleV1Models(res, ollamaUrl);
67578
67949
  return;
@@ -67639,7 +68010,14 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67639
68010
  limits: ep.limits ?? { maxRequestsPerMinute: "unlimited", maxTokensPerDay: "unlimited" }
67640
68011
  };
67641
68012
  }
67642
- jsonResponse(res, 200, { usage: usageData, totalTokensIn: metrics.totalTokensIn, totalTokensOut: metrics.totalTokensOut });
68013
+ const persistent = getUsageSummary();
68014
+ jsonResponse(res, 200, {
68015
+ usage: usageData,
68016
+ totalTokensIn: metrics.totalTokensIn,
68017
+ totalTokensOut: metrics.totalTokensOut,
68018
+ persistent
68019
+ // survives restarts
68020
+ });
67643
68021
  return;
67644
68022
  }
67645
68023
  if (pathname === "/v1/commands" && method === "GET") {
@@ -67788,19 +68166,20 @@ function startApiServer(options = {}) {
67788
68166
  const config = loadConfig();
67789
68167
  const ollamaUrl = options.ollamaUrl ?? config.backendUrl;
67790
68168
  const cwd4 = process.cwd();
67791
- initAuditLog(join71(cwd4, ".oa"));
68169
+ initAuditLog(join73(cwd4, ".oa"));
68170
+ initUsageTracker(join73(cwd4, ".oa"));
67792
68171
  const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
67793
68172
  if (retentionDays > 0) {
67794
68173
  try {
67795
- const jobsDir3 = join71(cwd4, ".oa", "jobs");
67796
- if (existsSync54(jobsDir3)) {
68174
+ const jobsDir3 = join73(cwd4, ".oa", "jobs");
68175
+ if (existsSync56(jobsDir3)) {
67797
68176
  const cutoff = Date.now() - retentionDays * 864e5;
67798
- for (const f of readdirSync21(jobsDir3)) {
68177
+ for (const f of readdirSync22(jobsDir3)) {
67799
68178
  if (!f.endsWith(".json"))
67800
68179
  continue;
67801
68180
  try {
67802
- const jobPath = join71(jobsDir3, f);
67803
- const job = JSON.parse(readFileSync43(jobPath, "utf-8"));
68181
+ const jobPath = join73(jobsDir3, f);
68182
+ const job = JSON.parse(readFileSync45(jobPath, "utf-8"));
67804
68183
  const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
67805
68184
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
67806
68185
  const { unlinkSync: unlinkSync13 } = __require("node:fs");
@@ -67820,8 +68199,8 @@ function startApiServer(options = {}) {
67820
68199
  if (useTls) {
67821
68200
  try {
67822
68201
  tlsOpts = {
67823
- cert: readFileSync43(resolve31(tlsCert)),
67824
- key: readFileSync43(resolve31(tlsKey))
68202
+ cert: readFileSync45(resolve31(tlsCert)),
68203
+ key: readFileSync45(resolve31(tlsKey))
67825
68204
  };
67826
68205
  } catch (e) {
67827
68206
  log2(`
@@ -67971,6 +68350,8 @@ var init_serve = __esm({
67971
68350
  init_logger();
67972
68351
  init_openapi();
67973
68352
  init_auth_oidc();
68353
+ init_chat_session();
68354
+ init_usage_tracker();
67974
68355
  init_oa_directory();
67975
68356
  init_render();
67976
68357
  init_profiles();
@@ -67993,11 +68374,11 @@ var init_serve = __esm({
67993
68374
 
67994
68375
  // packages/cli/dist/tui/interactive.js
67995
68376
  import { cwd } from "node:process";
67996
- import { resolve as resolve32, join as join72, dirname as dirname22, extname as extname11 } from "node:path";
68377
+ import { resolve as resolve32, join as join74, dirname as dirname22, extname as extname11 } from "node:path";
67997
68378
  import { createRequire as createRequire4 } from "node:module";
67998
68379
  import { fileURLToPath as fileURLToPath14 } from "node:url";
67999
- import { readFileSync as readFileSync44, writeFileSync as writeFileSync27, appendFileSync as appendFileSync5, rmSync as rmSync3, readdirSync as readdirSync22, mkdirSync as mkdirSync29 } from "node:fs";
68000
- import { existsSync as existsSync55 } from "node:fs";
68380
+ import { readFileSync as readFileSync46, writeFileSync as writeFileSync28, appendFileSync as appendFileSync5, rmSync as rmSync3, readdirSync as readdirSync23, mkdirSync as mkdirSync30 } from "node:fs";
68381
+ import { existsSync as existsSync57 } from "node:fs";
68001
68382
  import { execSync as execSync35 } from "node:child_process";
68002
68383
  import { homedir as homedir19 } from "node:os";
68003
68384
  function formatTimeAgo(date) {
@@ -68018,12 +68399,12 @@ function getVersion4() {
68018
68399
  const require2 = createRequire4(import.meta.url);
68019
68400
  const thisDir = dirname22(fileURLToPath14(import.meta.url));
68020
68401
  const candidates = [
68021
- join72(thisDir, "..", "package.json"),
68022
- join72(thisDir, "..", "..", "package.json"),
68023
- join72(thisDir, "..", "..", "..", "package.json")
68402
+ join74(thisDir, "..", "package.json"),
68403
+ join74(thisDir, "..", "..", "package.json"),
68404
+ join74(thisDir, "..", "..", "..", "package.json")
68024
68405
  ];
68025
68406
  for (const pkgPath of candidates) {
68026
- if (existsSync55(pkgPath)) {
68407
+ if (existsSync57(pkgPath)) {
68027
68408
  const pkg = require2(pkgPath);
68028
68409
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
68029
68410
  return pkg.version ?? "0.0.0";
@@ -68262,15 +68643,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
68262
68643
  function gatherMemorySnippets(root) {
68263
68644
  const snippets = [];
68264
68645
  const dirs = [
68265
- join72(root, ".oa", "memory"),
68266
- join72(root, ".open-agents", "memory")
68646
+ join74(root, ".oa", "memory"),
68647
+ join74(root, ".open-agents", "memory")
68267
68648
  ];
68268
68649
  for (const dir of dirs) {
68269
- if (!existsSync55(dir))
68650
+ if (!existsSync57(dir))
68270
68651
  continue;
68271
68652
  try {
68272
- for (const f of readdirSync22(dir).filter((f2) => f2.endsWith(".json"))) {
68273
- const data = JSON.parse(readFileSync44(join72(dir, f), "utf-8"));
68653
+ for (const f of readdirSync23(dir).filter((f2) => f2.endsWith(".json"))) {
68654
+ const data = JSON.parse(readFileSync46(join74(dir, f), "utf-8"));
68274
68655
  for (const val of Object.values(data)) {
68275
68656
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
68276
68657
  if (v.length > 10)
@@ -68427,9 +68808,9 @@ ${metabolismMemories}
68427
68808
  } catch {
68428
68809
  }
68429
68810
  try {
68430
- const archeFile = join72(repoRoot, ".oa", "arche", "variants.json");
68431
- if (existsSync55(archeFile)) {
68432
- const variants = JSON.parse(readFileSync44(archeFile, "utf8"));
68811
+ const archeFile = join74(repoRoot, ".oa", "arche", "variants.json");
68812
+ if (existsSync57(archeFile)) {
68813
+ const variants = JSON.parse(readFileSync46(archeFile, "utf8"));
68433
68814
  if (variants.length > 0) {
68434
68815
  let filtered = variants;
68435
68816
  if (taskType) {
@@ -68598,9 +68979,9 @@ RULES:
68598
68979
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
68599
68980
  let identityInjection = "";
68600
68981
  try {
68601
- const ikStateFile = join72(repoRoot, ".oa", "identity", "self-state.json");
68602
- if (existsSync55(ikStateFile)) {
68603
- const selfState = JSON.parse(readFileSync44(ikStateFile, "utf8"));
68982
+ const ikStateFile = join74(repoRoot, ".oa", "identity", "self-state.json");
68983
+ if (existsSync57(ikStateFile)) {
68984
+ const selfState = JSON.parse(readFileSync46(ikStateFile, "utf8"));
68604
68985
  const lines = [
68605
68986
  `[Identity State v${selfState.version}]`,
68606
68987
  `Self: ${selfState.narrative_summary}`,
@@ -69244,13 +69625,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69244
69625
  });
69245
69626
  }
69246
69627
  try {
69247
- const ikDir = join72(repoRoot, ".oa", "identity");
69248
- const ikFile = join72(ikDir, "self-state.json");
69628
+ const ikDir = join74(repoRoot, ".oa", "identity");
69629
+ const ikFile = join74(ikDir, "self-state.json");
69249
69630
  let ikState;
69250
- if (existsSync55(ikFile)) {
69251
- ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
69631
+ if (existsSync57(ikFile)) {
69632
+ ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
69252
69633
  } else {
69253
- mkdirSync29(ikDir, { recursive: true });
69634
+ mkdirSync30(ikDir, { recursive: true });
69254
69635
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
69255
69636
  ikState = {
69256
69637
  self_id: `oa-${machineId}`,
@@ -69276,7 +69657,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69276
69657
  }
69277
69658
  ikState.session_count = (ikState.session_count || 0) + 1;
69278
69659
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69279
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69660
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
69280
69661
  } catch (ikErr) {
69281
69662
  try {
69282
69663
  console.error("[IK-OBSERVE]", ikErr);
@@ -69291,14 +69672,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
69291
69672
  } else {
69292
69673
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
69293
69674
  try {
69294
- const ikFile = join72(repoRoot, ".oa", "identity", "self-state.json");
69295
- if (existsSync55(ikFile)) {
69296
- const ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
69675
+ const ikFile = join74(repoRoot, ".oa", "identity", "self-state.json");
69676
+ if (existsSync57(ikFile)) {
69677
+ const ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
69297
69678
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
69298
69679
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
69299
69680
  ikState.session_count = (ikState.session_count || 0) + 1;
69300
69681
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
69301
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
69682
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
69302
69683
  }
69303
69684
  } catch {
69304
69685
  }
@@ -69395,10 +69776,10 @@ async function startInteractive(config, repoPath) {
69395
69776
  process.stdin.pause();
69396
69777
  }
69397
69778
  try {
69398
- const oaDir = join72(repoRoot, ".oa");
69399
- const nexusPidFile = join72(oaDir, "nexus", "daemon.pid");
69400
- if (existsSync55(nexusPidFile)) {
69401
- const pid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
69779
+ const oaDir = join74(repoRoot, ".oa");
69780
+ const nexusPidFile = join74(oaDir, "nexus", "daemon.pid");
69781
+ if (existsSync57(nexusPidFile)) {
69782
+ const pid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
69402
69783
  if (pid > 0) {
69403
69784
  try {
69404
69785
  process.kill(pid, 0);
@@ -69735,7 +70116,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
69735
70116
  let p2pGateway = null;
69736
70117
  let peerMesh = null;
69737
70118
  let inferenceRouter = null;
69738
- const secretVault = new SecretVault(join72(repoRoot, ".oa", "vault.enc"));
70119
+ const secretVault = new SecretVault(join74(repoRoot, ".oa", "vault.enc"));
69739
70120
  let adminSessionKey = null;
69740
70121
  const callSubAgents = /* @__PURE__ */ new Map();
69741
70122
  const streamRenderer = new StreamRenderer();
@@ -69958,13 +70339,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
69958
70339
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
69959
70340
  return [hits, line];
69960
70341
  }
69961
- const HISTORY_DIR = join72(homedir19(), ".open-agents");
69962
- const HISTORY_FILE = join72(HISTORY_DIR, "repl-history");
70342
+ const HISTORY_DIR = join74(homedir19(), ".open-agents");
70343
+ const HISTORY_FILE = join74(HISTORY_DIR, "repl-history");
69963
70344
  const MAX_HISTORY_LINES = 500;
69964
70345
  let savedHistory = [];
69965
70346
  try {
69966
- if (existsSync55(HISTORY_FILE)) {
69967
- const raw = readFileSync44(HISTORY_FILE, "utf8").trim();
70347
+ if (existsSync57(HISTORY_FILE)) {
70348
+ const raw = readFileSync46(HISTORY_FILE, "utf8").trim();
69968
70349
  if (raw)
69969
70350
  savedHistory = raw.split("\n").reverse();
69970
70351
  }
@@ -70067,12 +70448,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70067
70448
  if (!line.trim())
70068
70449
  return;
70069
70450
  try {
70070
- mkdirSync29(HISTORY_DIR, { recursive: true });
70451
+ mkdirSync30(HISTORY_DIR, { recursive: true });
70071
70452
  appendFileSync5(HISTORY_FILE, line + "\n", "utf8");
70072
70453
  if (Math.random() < 0.02) {
70073
- const all = readFileSync44(HISTORY_FILE, "utf8").trim().split("\n");
70454
+ const all = readFileSync46(HISTORY_FILE, "utf8").trim().split("\n");
70074
70455
  if (all.length > MAX_HISTORY_LINES) {
70075
- writeFileSync27(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
70456
+ writeFileSync28(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
70076
70457
  }
70077
70458
  }
70078
70459
  } catch {
@@ -70256,7 +70637,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70256
70637
  } catch {
70257
70638
  }
70258
70639
  try {
70259
- const oaDir = join72(repoRoot, ".oa");
70640
+ const oaDir = join74(repoRoot, ".oa");
70260
70641
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
70261
70642
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
70262
70643
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -70288,7 +70669,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70288
70669
  } catch {
70289
70670
  }
70290
70671
  try {
70291
- const oaDir = join72(repoRoot, ".oa");
70672
+ const oaDir = join74(repoRoot, ".oa");
70292
70673
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
70293
70674
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
70294
70675
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -70329,11 +70710,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
70329
70710
  }
70330
70711
  try {
70331
70712
  const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
70332
- const globalNamePath = join72(_hd(), ".open-agents", "agent-name");
70713
+ const globalNamePath = join74(_hd(), ".open-agents", "agent-name");
70333
70714
  let agName = "";
70334
70715
  try {
70335
- if (existsSync55(globalNamePath))
70336
- agName = readFileSync44(globalNamePath, "utf8").trim();
70716
+ if (existsSync57(globalNamePath))
70717
+ agName = readFileSync46(globalNamePath, "utf8").trim();
70337
70718
  } catch {
70338
70719
  }
70339
70720
  if (!agName) {
@@ -71309,7 +71690,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71309
71690
  kind,
71310
71691
  targetUrl,
71311
71692
  authKey,
71312
- stateDir: join72(repoRoot, ".oa"),
71693
+ stateDir: join74(repoRoot, ".oa"),
71313
71694
  passthrough: passthrough ?? false,
71314
71695
  loadbalance: loadbalance ?? false,
71315
71696
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -71355,7 +71736,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71355
71736
  await tunnelGateway.stop();
71356
71737
  tunnelGateway = null;
71357
71738
  }
71358
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join72(repoRoot, ".oa") });
71739
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join74(repoRoot, ".oa") });
71359
71740
  newTunnel.on("stats", (stats) => {
71360
71741
  statusBar.setExposeStatus({
71361
71742
  status: stats.status,
@@ -71444,9 +71825,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71444
71825
  if (!result.success)
71445
71826
  throw new Error(result.error || "Connect failed");
71446
71827
  try {
71447
- const nexusPidFile = join72(repoRoot, ".oa", "nexus", "daemon.pid");
71448
- if (existsSync55(nexusPidFile)) {
71449
- const pid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
71828
+ const nexusPidFile = join74(repoRoot, ".oa", "nexus", "daemon.pid");
71829
+ if (existsSync57(nexusPidFile)) {
71830
+ const pid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
71450
71831
  if (pid > 0) {
71451
71832
  registry.register({
71452
71833
  name: "Nexus",
@@ -71642,10 +72023,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71642
72023
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
71643
72024
  }
71644
72025
  try {
71645
- const nexusDir = join72(repoRoot, OA_DIR, "nexus");
71646
- const pidFile = join72(nexusDir, "daemon.pid");
71647
- if (existsSync55(pidFile)) {
71648
- const pid = parseInt(readFileSync44(pidFile, "utf8").trim(), 10);
72026
+ const nexusDir = join74(repoRoot, OA_DIR, "nexus");
72027
+ const pidFile = join74(nexusDir, "daemon.pid");
72028
+ if (existsSync57(pidFile)) {
72029
+ const pid = parseInt(readFileSync46(pidFile, "utf8").trim(), 10);
71649
72030
  if (pid > 0) {
71650
72031
  try {
71651
72032
  if (process.platform === "win32") {
@@ -71667,13 +72048,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71667
72048
  } catch {
71668
72049
  }
71669
72050
  try {
71670
- const voiceDir2 = join72(homedir19(), ".open-agents", "voice");
72051
+ const voiceDir2 = join74(homedir19(), ".open-agents", "voice");
71671
72052
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
71672
72053
  for (const pf of voicePidFiles) {
71673
- const pidPath = join72(voiceDir2, pf);
71674
- if (existsSync55(pidPath)) {
72054
+ const pidPath = join74(voiceDir2, pf);
72055
+ if (existsSync57(pidPath)) {
71675
72056
  try {
71676
- const pid = parseInt(readFileSync44(pidPath, "utf8").trim(), 10);
72057
+ const pid = parseInt(readFileSync46(pidPath, "utf8").trim(), 10);
71677
72058
  if (pid > 0) {
71678
72059
  if (process.platform === "win32") {
71679
72060
  try {
@@ -71697,8 +72078,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71697
72078
  execSync35(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
71698
72079
  } catch {
71699
72080
  }
71700
- const oaPath = join72(repoRoot, OA_DIR);
71701
- if (existsSync55(oaPath)) {
72081
+ const oaPath = join74(repoRoot, OA_DIR);
72082
+ if (existsSync57(oaPath)) {
71702
72083
  let deleted = false;
71703
72084
  for (let attempt = 0; attempt < 3; attempt++) {
71704
72085
  try {
@@ -71781,19 +72162,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
71781
72162
  try {
71782
72163
  const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
71783
72164
  if (isPersonaPlexRunning2()) {
71784
- const ppPidFile = join72(homedir19(), ".open-agents", "voice", "personaplex", "daemon.pid");
71785
- const ppPortFile = join72(homedir19(), ".open-agents", "voice", "personaplex", "daemon.port");
71786
- if (existsSync55(ppPidFile)) {
71787
- const ppPid = parseInt(readFileSync44(ppPidFile, "utf8").trim(), 10);
71788
- const ppPort = existsSync55(ppPortFile) ? parseInt(readFileSync44(ppPortFile, "utf8").trim(), 10) : void 0;
72165
+ const ppPidFile = join74(homedir19(), ".open-agents", "voice", "personaplex", "daemon.pid");
72166
+ const ppPortFile = join74(homedir19(), ".open-agents", "voice", "personaplex", "daemon.port");
72167
+ if (existsSync57(ppPidFile)) {
72168
+ const ppPid = parseInt(readFileSync46(ppPidFile, "utf8").trim(), 10);
72169
+ const ppPort = existsSync57(ppPortFile) ? parseInt(readFileSync46(ppPortFile, "utf8").trim(), 10) : void 0;
71789
72170
  if (ppPid > 0 && !registry.daemons.has("PersonaPlex")) {
71790
72171
  registry.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
71791
72172
  }
71792
72173
  }
71793
72174
  }
71794
- const nexusPidFile = join72(repoRoot, ".oa", "nexus", "daemon.pid");
71795
- if (existsSync55(nexusPidFile)) {
71796
- const nPid = parseInt(readFileSync44(nexusPidFile, "utf8").trim(), 10);
72175
+ const nexusPidFile = join74(repoRoot, ".oa", "nexus", "daemon.pid");
72176
+ if (existsSync57(nexusPidFile)) {
72177
+ const nPid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
71797
72178
  if (nPid > 0 && !registry.daemons.has("Nexus")) {
71798
72179
  try {
71799
72180
  process.kill(nPid, 0);
@@ -72135,8 +72516,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
72135
72516
  }
72136
72517
  }
72137
72518
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
72138
- const isImage = isImagePath(cleanPath) && existsSync55(resolve32(repoRoot, cleanPath));
72139
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync55(resolve32(repoRoot, cleanPath));
72519
+ const isImage = isImagePath(cleanPath) && existsSync57(resolve32(repoRoot, cleanPath));
72520
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync57(resolve32(repoRoot, cleanPath));
72140
72521
  if (activeTask) {
72141
72522
  if (activeTask.runner.isPaused) {
72142
72523
  activeTask.runner.resume();
@@ -72145,7 +72526,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
72145
72526
  if (isImage) {
72146
72527
  try {
72147
72528
  const imgPath = resolve32(repoRoot, cleanPath);
72148
- const imgBuffer = readFileSync44(imgPath);
72529
+ const imgBuffer = readFileSync46(imgPath);
72149
72530
  const base64 = imgBuffer.toString("base64");
72150
72531
  const ext = extname11(cleanPath).toLowerCase();
72151
72532
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -72360,7 +72741,7 @@ Summarize or analyze this transcription as appropriate.`;
72360
72741
 
72361
72742
  NEW TASK: ${fullInput}`;
72362
72743
  restoredSessionContext = null;
72363
- } else if (existsSync55(join72(repoRoot, ".oa", "context", "session-diary.md"))) {
72744
+ } else if (existsSync57(join74(repoRoot, ".oa", "context", "session-diary.md"))) {
72364
72745
  taskInput = `[Previous sessions exist \u2014 file_read(".oa/context/session-diary.md") to recall]
72365
72746
 
72366
72747
  ${fullInput}`;
@@ -72677,13 +73058,13 @@ async function runWithTUI(task, config, repoPath) {
72677
73058
  const handle = startTask(task, config, repoRoot);
72678
73059
  await handle.promise;
72679
73060
  try {
72680
- const ikDir = join72(repoRoot, ".oa", "identity");
72681
- const ikFile = join72(ikDir, "self-state.json");
73061
+ const ikDir = join74(repoRoot, ".oa", "identity");
73062
+ const ikFile = join74(ikDir, "self-state.json");
72682
73063
  let ikState;
72683
- if (existsSync55(ikFile)) {
72684
- ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
73064
+ if (existsSync57(ikFile)) {
73065
+ ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
72685
73066
  } else {
72686
- mkdirSync29(ikDir, { recursive: true });
73067
+ mkdirSync30(ikDir, { recursive: true });
72687
73068
  ikState = {
72688
73069
  self_id: `oa-${Date.now().toString(36)}`,
72689
73070
  version: 1,
@@ -72705,7 +73086,7 @@ async function runWithTUI(task, config, repoPath) {
72705
73086
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
72706
73087
  ikState.session_count = (ikState.session_count || 0) + 1;
72707
73088
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
72708
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
73089
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
72709
73090
  } catch (ikErr) {
72710
73091
  }
72711
73092
  try {
@@ -72714,12 +73095,12 @@ async function runWithTUI(task, config, repoPath) {
72714
73095
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
72715
73096
  } catch {
72716
73097
  try {
72717
- const archeDir = join72(repoRoot, ".oa", "arche");
72718
- const archeFile = join72(archeDir, "variants.json");
73098
+ const archeDir = join74(repoRoot, ".oa", "arche");
73099
+ const archeFile = join74(archeDir, "variants.json");
72719
73100
  let variants = [];
72720
73101
  try {
72721
- if (existsSync55(archeFile))
72722
- variants = JSON.parse(readFileSync44(archeFile, "utf8"));
73102
+ if (existsSync57(archeFile))
73103
+ variants = JSON.parse(readFileSync46(archeFile, "utf8"));
72723
73104
  } catch {
72724
73105
  }
72725
73106
  variants.push({
@@ -72734,16 +73115,16 @@ async function runWithTUI(task, config, repoPath) {
72734
73115
  });
72735
73116
  if (variants.length > 50)
72736
73117
  variants = variants.slice(-50);
72737
- mkdirSync29(archeDir, { recursive: true });
72738
- writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
73118
+ mkdirSync30(archeDir, { recursive: true });
73119
+ writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
72739
73120
  } catch {
72740
73121
  }
72741
73122
  }
72742
73123
  try {
72743
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72744
- if (existsSync55(metaFile)) {
72745
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72746
- 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);
73124
+ const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
73125
+ if (existsSync57(metaFile)) {
73126
+ const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
73127
+ 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);
72747
73128
  let updated = false;
72748
73129
  for (const item of surfaced) {
72749
73130
  item.accessCount = (item.accessCount || 0) + 1;
@@ -72753,7 +73134,7 @@ async function runWithTUI(task, config, repoPath) {
72753
73134
  updated = true;
72754
73135
  }
72755
73136
  if (updated) {
72756
- writeFileSync27(metaFile, JSON.stringify(store, null, 2));
73137
+ writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
72757
73138
  }
72758
73139
  }
72759
73140
  } catch {
@@ -72806,9 +73187,9 @@ Rules:
72806
73187
  try {
72807
73188
  const { initDb: initDb2 } = __require("@open-agents/memory");
72808
73189
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
72809
- const dbDir = join72(repoRoot, ".oa", "memory");
72810
- mkdirSync29(dbDir, { recursive: true });
72811
- const db = initDb2(join72(dbDir, "structured.db"));
73190
+ const dbDir = join74(repoRoot, ".oa", "memory");
73191
+ mkdirSync30(dbDir, { recursive: true });
73192
+ const db = initDb2(join74(dbDir, "structured.db"));
72812
73193
  const memStore = new ProceduralMemoryStore2(db);
72813
73194
  memStore.createWithEmbedding({
72814
73195
  content: content.slice(0, 600),
@@ -72823,15 +73204,15 @@ Rules:
72823
73204
  db.close();
72824
73205
  } catch {
72825
73206
  }
72826
- const metaDir = join72(repoRoot, ".oa", "memory", "metabolism");
72827
- const storeFile = join72(metaDir, "store.json");
72828
- let store = [];
73207
+ const metaDir = join74(repoRoot, ".oa", "memory", "metabolism");
73208
+ const storeFile = join74(metaDir, "store.json");
73209
+ let store2 = [];
72829
73210
  try {
72830
- if (existsSync55(storeFile))
72831
- store = JSON.parse(readFileSync44(storeFile, "utf8"));
73211
+ if (existsSync57(storeFile))
73212
+ store2 = JSON.parse(readFileSync46(storeFile, "utf8"));
72832
73213
  } catch {
72833
73214
  }
72834
- store.push({
73215
+ store2.push({
72835
73216
  id: `mem-traj-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
72836
73217
  type: "procedural",
72837
73218
  content: content.slice(0, 600),
@@ -72842,29 +73223,29 @@ Rules:
72842
73223
  lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString(),
72843
73224
  accessCount: 0
72844
73225
  });
72845
- if (store.length > 100)
72846
- store = store.slice(-100);
72847
- mkdirSync29(metaDir, { recursive: true });
72848
- writeFileSync27(storeFile, JSON.stringify(store, null, 2));
73226
+ if (store2.length > 100)
73227
+ store2 = store2.slice(-100);
73228
+ mkdirSync30(metaDir, { recursive: true });
73229
+ writeFileSync28(storeFile, JSON.stringify(store2, null, 2));
72849
73230
  }
72850
73231
  }
72851
73232
  } catch {
72852
73233
  }
72853
73234
  try {
72854
- const cohereSettingsFile = join72(repoRoot, ".oa", "settings.json");
73235
+ const cohereSettingsFile = join74(repoRoot, ".oa", "settings.json");
72855
73236
  let cohereActive = false;
72856
73237
  try {
72857
- if (existsSync55(cohereSettingsFile)) {
72858
- const settings = JSON.parse(readFileSync44(cohereSettingsFile, "utf8"));
73238
+ if (existsSync57(cohereSettingsFile)) {
73239
+ const settings = JSON.parse(readFileSync46(cohereSettingsFile, "utf8"));
72859
73240
  cohereActive = settings.cohere === true;
72860
73241
  }
72861
73242
  } catch {
72862
73243
  }
72863
73244
  if (cohereActive) {
72864
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72865
- if (existsSync55(metaFile)) {
72866
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72867
- const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
73245
+ const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
73246
+ if (existsSync57(metaFile)) {
73247
+ const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
73248
+ const latest = store2.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
72868
73249
  if (latest && latest.scores?.confidence >= 0.6) {
72869
73250
  try {
72870
73251
  const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
@@ -72888,34 +73269,34 @@ Rules:
72888
73269
  }
72889
73270
  } catch (err) {
72890
73271
  try {
72891
- const ikFile = join72(repoRoot, ".oa", "identity", "self-state.json");
72892
- if (existsSync55(ikFile)) {
72893
- const ikState = JSON.parse(readFileSync44(ikFile, "utf8"));
73272
+ const ikFile = join74(repoRoot, ".oa", "identity", "self-state.json");
73273
+ if (existsSync57(ikFile)) {
73274
+ const ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
72894
73275
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
72895
73276
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
72896
73277
  ikState.session_count = (ikState.session_count || 0) + 1;
72897
73278
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
72898
- writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
73279
+ writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
72899
73280
  }
72900
- const metaFile = join72(repoRoot, ".oa", "memory", "metabolism", "store.json");
72901
- if (existsSync55(metaFile)) {
72902
- const store = JSON.parse(readFileSync44(metaFile, "utf8"));
72903
- 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);
73281
+ const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
73282
+ if (existsSync57(metaFile)) {
73283
+ const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
73284
+ 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);
72904
73285
  for (const item of surfaced) {
72905
73286
  item.accessCount = (item.accessCount || 0) + 1;
72906
73287
  item.lastAccessedAt = (/* @__PURE__ */ new Date()).toISOString();
72907
73288
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
72908
73289
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
72909
73290
  }
72910
- writeFileSync27(metaFile, JSON.stringify(store, null, 2));
73291
+ writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
72911
73292
  }
72912
73293
  try {
72913
- const archeDir = join72(repoRoot, ".oa", "arche");
72914
- const archeFile = join72(archeDir, "variants.json");
73294
+ const archeDir = join74(repoRoot, ".oa", "arche");
73295
+ const archeFile = join74(archeDir, "variants.json");
72915
73296
  let variants = [];
72916
73297
  try {
72917
- if (existsSync55(archeFile))
72918
- variants = JSON.parse(readFileSync44(archeFile, "utf8"));
73298
+ if (existsSync57(archeFile))
73299
+ variants = JSON.parse(readFileSync46(archeFile, "utf8"));
72919
73300
  } catch {
72920
73301
  }
72921
73302
  variants.push({
@@ -72930,8 +73311,8 @@ Rules:
72930
73311
  });
72931
73312
  if (variants.length > 50)
72932
73313
  variants = variants.slice(-50);
72933
- mkdirSync29(archeDir, { recursive: true });
72934
- writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
73314
+ mkdirSync30(archeDir, { recursive: true });
73315
+ writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
72935
73316
  } catch {
72936
73317
  }
72937
73318
  } catch {
@@ -73001,13 +73382,13 @@ __export(run_exports, {
73001
73382
  });
73002
73383
  import { resolve as resolve33 } from "node:path";
73003
73384
  import { spawn as spawn22 } from "node:child_process";
73004
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync28, readFileSync as readFileSync45, readdirSync as readdirSync23, existsSync as existsSync56 } from "node:fs";
73385
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29, readFileSync as readFileSync47, readdirSync as readdirSync24, existsSync as existsSync58 } from "node:fs";
73005
73386
  import { randomBytes as randomBytes17 } from "node:crypto";
73006
- import { join as join73 } from "node:path";
73387
+ import { join as join75 } from "node:path";
73007
73388
  function jobsDir2(repoPath) {
73008
73389
  const root = resolve33(repoPath ?? process.cwd());
73009
- const dir = join73(root, ".oa", "jobs");
73010
- mkdirSync30(dir, { recursive: true });
73390
+ const dir = join75(root, ".oa", "jobs");
73391
+ mkdirSync31(dir, { recursive: true });
73011
73392
  return dir;
73012
73393
  }
73013
73394
  async function runCommand(opts, config) {
@@ -73092,7 +73473,7 @@ async function runBackground(task, config, opts) {
73092
73473
  });
73093
73474
  child.unref();
73094
73475
  job.pid = child.pid ?? 0;
73095
- writeFileSync28(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
73476
+ writeFileSync29(join75(dir, `${id}.json`), JSON.stringify(job, null, 2));
73096
73477
  let output = "";
73097
73478
  child.stdout?.on("data", (chunk) => {
73098
73479
  output += chunk.toString();
@@ -73108,7 +73489,7 @@ async function runBackground(task, config, opts) {
73108
73489
  job.summary = result.summary;
73109
73490
  job.durationMs = result.durationMs;
73110
73491
  job.error = result.error;
73111
- writeFileSync28(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
73492
+ writeFileSync29(join75(dir, `${id}.json`), JSON.stringify(job, null, 2));
73112
73493
  } catch {
73113
73494
  }
73114
73495
  });
@@ -73124,13 +73505,13 @@ async function runBackground(task, config, opts) {
73124
73505
  }
73125
73506
  function statusCommand(jobId, repoPath) {
73126
73507
  const dir = jobsDir2(repoPath);
73127
- const file = join73(dir, `${jobId}.json`);
73128
- if (!existsSync56(file)) {
73508
+ const file = join75(dir, `${jobId}.json`);
73509
+ if (!existsSync58(file)) {
73129
73510
  console.error(`Job not found: ${jobId}`);
73130
73511
  console.log(`Available jobs: oa jobs`);
73131
73512
  process.exit(1);
73132
73513
  }
73133
- const job = JSON.parse(readFileSync45(file, "utf-8"));
73514
+ const job = JSON.parse(readFileSync47(file, "utf-8"));
73134
73515
  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`;
73135
73516
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
73136
73517
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -73145,7 +73526,7 @@ function statusCommand(jobId, repoPath) {
73145
73526
  }
73146
73527
  function jobsCommand(repoPath) {
73147
73528
  const dir = jobsDir2(repoPath);
73148
- const files = readdirSync23(dir).filter((f) => f.endsWith(".json")).sort();
73529
+ const files = readdirSync24(dir).filter((f) => f.endsWith(".json")).sort();
73149
73530
  if (files.length === 0) {
73150
73531
  console.log("No jobs found.");
73151
73532
  return;
@@ -73153,7 +73534,7 @@ function jobsCommand(repoPath) {
73153
73534
  console.log("Jobs:");
73154
73535
  for (const file of files) {
73155
73536
  try {
73156
- const job = JSON.parse(readFileSync45(join73(dir, file), "utf-8"));
73537
+ const job = JSON.parse(readFileSync47(join75(dir, file), "utf-8"));
73157
73538
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
73158
73539
  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`;
73159
73540
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -73173,7 +73554,7 @@ import { glob } from "glob";
73173
73554
  import ignore from "ignore";
73174
73555
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
73175
73556
  import { createHash as createHash6 } from "node:crypto";
73176
- import { join as join74, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
73557
+ import { join as join76, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
73177
73558
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
73178
73559
  var init_codebase_indexer = __esm({
73179
73560
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -73217,7 +73598,7 @@ var init_codebase_indexer = __esm({
73217
73598
  const ig = ignore.default();
73218
73599
  if (this.config.respectGitignore) {
73219
73600
  try {
73220
- const gitignoreContent = await readFile23(join74(this.config.rootDir, ".gitignore"), "utf-8");
73601
+ const gitignoreContent = await readFile23(join76(this.config.rootDir, ".gitignore"), "utf-8");
73221
73602
  ig.add(gitignoreContent);
73222
73603
  } catch {
73223
73604
  }
@@ -73232,7 +73613,7 @@ var init_codebase_indexer = __esm({
73232
73613
  for (const relativePath of files) {
73233
73614
  if (ig.ignores(relativePath))
73234
73615
  continue;
73235
- const fullPath = join74(this.config.rootDir, relativePath);
73616
+ const fullPath = join76(this.config.rootDir, relativePath);
73236
73617
  try {
73237
73618
  const fileStat = await stat4(fullPath);
73238
73619
  if (fileStat.size > this.config.maxFileSize)
@@ -73278,7 +73659,7 @@ var init_codebase_indexer = __esm({
73278
73659
  if (!child) {
73279
73660
  child = {
73280
73661
  name: part,
73281
- path: join74(current.path, part),
73662
+ path: join76(current.path, part),
73282
73663
  type: "directory",
73283
73664
  children: []
73284
73665
  };
@@ -73361,13 +73742,13 @@ __export(index_repo_exports, {
73361
73742
  indexRepoCommand: () => indexRepoCommand
73362
73743
  });
73363
73744
  import { resolve as resolve34 } from "node:path";
73364
- import { existsSync as existsSync57, statSync as statSync17 } from "node:fs";
73745
+ import { existsSync as existsSync59, statSync as statSync17 } from "node:fs";
73365
73746
  import { cwd as cwd2 } from "node:process";
73366
73747
  async function indexRepoCommand(opts, _config) {
73367
73748
  const repoRoot = resolve34(opts.repoPath ?? cwd2());
73368
73749
  printHeader("Index Repository");
73369
73750
  printInfo(`Indexing: ${repoRoot}`);
73370
- if (!existsSync57(repoRoot)) {
73751
+ if (!existsSync59(repoRoot)) {
73371
73752
  printError(`Path does not exist: ${repoRoot}`);
73372
73753
  process.exit(1);
73373
73754
  }
@@ -73619,7 +74000,7 @@ var config_exports2 = {};
73619
74000
  __export(config_exports2, {
73620
74001
  configCommand: () => configCommand
73621
74002
  });
73622
- import { join as join75, resolve as resolve35 } from "node:path";
74003
+ import { join as join77, resolve as resolve35 } from "node:path";
73623
74004
  import { homedir as homedir20 } from "node:os";
73624
74005
  import { cwd as cwd3 } from "node:process";
73625
74006
  function redactIfSensitive(key, value) {
@@ -73702,7 +74083,7 @@ function handleShow(opts, config) {
73702
74083
  }
73703
74084
  }
73704
74085
  printSection("Config File");
73705
- printInfo(`~/.open-agents/config.json (${join75(homedir20(), ".open-agents", "config.json")})`);
74086
+ printInfo(`~/.open-agents/config.json (${join77(homedir20(), ".open-agents", "config.json")})`);
73706
74087
  printSection("Priority Chain");
73707
74088
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
73708
74089
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -73741,7 +74122,7 @@ function handleSet(opts, _config) {
73741
74122
  const coerced = coerceForSettings(key, value);
73742
74123
  saveProjectSettings(repoRoot, { [key]: coerced });
73743
74124
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
73744
- printInfo(`Saved to ${join75(repoRoot, ".oa", "settings.json")}`);
74125
+ printInfo(`Saved to ${join77(repoRoot, ".oa", "settings.json")}`);
73745
74126
  printInfo("This override applies only when running in this workspace.");
73746
74127
  } catch (err) {
73747
74128
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -73884,8 +74265,8 @@ __export(eval_exports, {
73884
74265
  evalCommand: () => evalCommand
73885
74266
  });
73886
74267
  import { tmpdir as tmpdir10 } from "node:os";
73887
- import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29 } from "node:fs";
73888
- import { join as join76 } from "node:path";
74268
+ import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30 } from "node:fs";
74269
+ import { join as join78 } from "node:path";
73889
74270
  async function evalCommand(opts, config) {
73890
74271
  const suiteName = opts.suite ?? "basic";
73891
74272
  const suite = SUITES[suiteName];
@@ -74010,9 +74391,9 @@ async function evalCommand(opts, config) {
74010
74391
  process.exit(failed > 0 ? 1 : 0);
74011
74392
  }
74012
74393
  function createTempEvalRepo() {
74013
- const dir = join76(tmpdir10(), `open-agents-eval-${Date.now()}`);
74014
- mkdirSync31(dir, { recursive: true });
74015
- writeFileSync29(join76(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
74394
+ const dir = join78(tmpdir10(), `open-agents-eval-${Date.now()}`);
74395
+ mkdirSync32(dir, { recursive: true });
74396
+ writeFileSync30(join78(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
74016
74397
  return dir;
74017
74398
  }
74018
74399
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -74072,7 +74453,7 @@ init_updater();
74072
74453
  import { parseArgs as nodeParseArgs2 } from "node:util";
74073
74454
  import { createRequire as createRequire5 } from "node:module";
74074
74455
  import { fileURLToPath as fileURLToPath15 } from "node:url";
74075
- import { dirname as dirname23, join as join77 } from "node:path";
74456
+ import { dirname as dirname23, join as join79 } from "node:path";
74076
74457
 
74077
74458
  // packages/cli/dist/cli.js
74078
74459
  import { createInterface } from "node:readline";
@@ -74179,7 +74560,7 @@ init_output();
74179
74560
  function getVersion5() {
74180
74561
  try {
74181
74562
  const require2 = createRequire5(import.meta.url);
74182
- const pkgPath = join77(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
74563
+ const pkgPath = join79(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
74183
74564
  const pkg = require2(pkgPath);
74184
74565
  return pkg.version;
74185
74566
  } catch {
@@ -74454,12 +74835,12 @@ function crashLog(label, err) {
74454
74835
  const logLine = `[${timestamp}] ${label}: ${msg}
74455
74836
  `;
74456
74837
  try {
74457
- const { appendFileSync: appendFileSync6, mkdirSync: mkdirSync32 } = __require("node:fs");
74458
- const { join: join78 } = __require("node:path");
74838
+ const { appendFileSync: appendFileSync6, mkdirSync: mkdirSync33 } = __require("node:fs");
74839
+ const { join: join80 } = __require("node:path");
74459
74840
  const { homedir: homedir21 } = __require("node:os");
74460
- const logDir = join78(homedir21(), ".open-agents");
74461
- mkdirSync32(logDir, { recursive: true });
74462
- appendFileSync6(join78(logDir, "crash.log"), logLine);
74841
+ const logDir = join80(homedir21(), ".open-agents");
74842
+ mkdirSync33(logDir, { recursive: true });
74843
+ appendFileSync6(join80(logDir, "crash.log"), logLine);
74463
74844
  } catch {
74464
74845
  }
74465
74846
  try {