open-agents-ai 0.184.36 → 0.184.38

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 +523 -244
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10679,8 +10679,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
10679
10679
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
10680
10680
  const filePath = join16(dir, `${name}.json`);
10681
10681
  if (existsSync13(filePath)) {
10682
- const { unlinkSync: unlinkSync12 } = __require("node:fs");
10683
- unlinkSync12(filePath);
10682
+ const { unlinkSync: unlinkSync13 } = __require("node:fs");
10683
+ unlinkSync13(filePath);
10684
10684
  return true;
10685
10685
  }
10686
10686
  return false;
@@ -11855,8 +11855,8 @@ async function loadTranscribeCli() {
11855
11855
  const nvmBase = join19(homedir7(), ".nvm", "versions", "node");
11856
11856
  if (existsSync16(nvmBase)) {
11857
11857
  try {
11858
- const { readdirSync: readdirSync22 } = await import("node:fs");
11859
- for (const ver of readdirSync22(nvmBase)) {
11858
+ const { readdirSync: readdirSync23 } = await import("node:fs");
11859
+ for (const ver of readdirSync23(nvmBase)) {
11860
11860
  const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
11861
11861
  if (existsSync16(join19(tcPath, "dist", "index.js"))) {
11862
11862
  const { createRequire: createRequire5 } = await import("node:module");
@@ -12909,13 +12909,13 @@ Justification: ${justification || "(none provided)"}`,
12909
12909
  }
12910
12910
  const snapshot = JSON.stringify(this.selfState, null, 2);
12911
12911
  try {
12912
- const { createHash: createHash6 } = await import("node:crypto");
12912
+ const { createHash: createHash7 } = await import("node:crypto");
12913
12913
  const snapshotDir = join21(this.cwd, ".oa", "identity", "snapshots");
12914
12914
  await mkdir5(snapshotDir, { recursive: true });
12915
12915
  const version = this.selfState.version;
12916
12916
  const snapshotPath = join21(snapshotDir, `v${version}.json`);
12917
12917
  await writeFile9(snapshotPath, snapshot, "utf8");
12918
- const hash = createHash6("sha256").update(snapshot).digest("hex");
12918
+ const hash = createHash7("sha256").update(snapshot).digest("hex");
12919
12919
  await writeFile9(join21(this.cwd, ".oa", "identity", "latest-hash.txt"), hash, "utf8");
12920
12920
  let ipfsCid = "";
12921
12921
  try {
@@ -13048,8 +13048,8 @@ New: ${newNarrative.slice(0, 200)}...`,
13048
13048
  }
13049
13049
  // ── Helpers ──────────────────────────────────────────────────────────────
13050
13050
  createDefaultState() {
13051
- const { createHash: createHash6 } = __require("node:crypto");
13052
- const machineId = createHash6("sha256").update(this.cwd).digest("hex").slice(0, 12);
13051
+ const { createHash: createHash7 } = __require("node:crypto");
13052
+ const machineId = createHash7("sha256").update(this.cwd).digest("hex").slice(0, 12);
13053
13053
  return {
13054
13054
  self_id: `oa-${machineId}`,
13055
13055
  version: 1,
@@ -13598,9 +13598,9 @@ print("${sentinel}")
13598
13598
  if (!this.proc || this.proc.killed) {
13599
13599
  return { success: false, path: "" };
13600
13600
  }
13601
- const { mkdirSync: mkdirSync28, writeFileSync: writeFileSync27 } = await import("node:fs");
13601
+ const { mkdirSync: mkdirSync29, writeFileSync: writeFileSync28 } = await import("node:fs");
13602
13602
  const sessionDir = join22(this.cwd, ".oa", "rlm");
13603
- mkdirSync28(sessionDir, { recursive: true });
13603
+ mkdirSync29(sessionDir, { recursive: true });
13604
13604
  const sessionPath = join22(sessionDir, "session.json");
13605
13605
  try {
13606
13606
  const inspectCode = `
@@ -13624,7 +13624,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13624
13624
  trajectoryCount: this.trajectory.length,
13625
13625
  subCallCount: this.subCallCount
13626
13626
  };
13627
- writeFileSync27(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13627
+ writeFileSync28(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
13628
13628
  return { success: true, path: sessionPath };
13629
13629
  }
13630
13630
  } catch {
@@ -13636,11 +13636,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
13636
13636
  * what was previously computed. */
13637
13637
  async loadSessionInfo() {
13638
13638
  try {
13639
- const { readFileSync: readFileSync42, existsSync: existsSync54 } = await import("node:fs");
13639
+ const { readFileSync: readFileSync43, existsSync: existsSync55 } = await import("node:fs");
13640
13640
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13641
- if (!existsSync54(sessionPath))
13641
+ if (!existsSync55(sessionPath))
13642
13642
  return null;
13643
- return JSON.parse(readFileSync42(sessionPath, "utf8"));
13643
+ return JSON.parse(readFileSync43(sessionPath, "utf8"));
13644
13644
  } catch {
13645
13645
  return null;
13646
13646
  }
@@ -13817,10 +13817,10 @@ var init_memory_metabolism = __esm({
13817
13817
  const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
13818
13818
  let lessons = [];
13819
13819
  try {
13820
- const { readdirSync: readdirSync22, readFileSync: readFileSync42 } = await import("node:fs");
13821
- const files = readdirSync22(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
13820
+ const { readdirSync: readdirSync23, readFileSync: readFileSync43 } = await import("node:fs");
13821
+ const files = readdirSync23(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
13822
13822
  for (const file of files) {
13823
- const lines = readFileSync42(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13823
+ const lines = readFileSync43(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
13824
13824
  for (const line of lines) {
13825
13825
  try {
13826
13826
  const entry = JSON.parse(line);
@@ -14204,14 +14204,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14204
14204
  * Optionally filter by task type for phase-aware context (FSM paper insight).
14205
14205
  */
14206
14206
  getTopMemoriesSync(k = 5, taskType) {
14207
- const { readFileSync: readFileSync42, existsSync: existsSync54 } = __require("node:fs");
14207
+ const { readFileSync: readFileSync43, existsSync: existsSync55 } = __require("node:fs");
14208
14208
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14209
14209
  const storeFile = join23(metaDir, "store.json");
14210
- if (!existsSync54(storeFile))
14210
+ if (!existsSync55(storeFile))
14211
14211
  return "";
14212
14212
  let store = [];
14213
14213
  try {
14214
- store = JSON.parse(readFileSync42(storeFile, "utf8"));
14214
+ store = JSON.parse(readFileSync43(storeFile, "utf8"));
14215
14215
  } catch {
14216
14216
  return "";
14217
14217
  }
@@ -14233,14 +14233,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14233
14233
  /** Update memory scores based on task outcome. Called after task completion.
14234
14234
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
14235
14235
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
14236
- const { readFileSync: readFileSync42, writeFileSync: writeFileSync27, existsSync: existsSync54, mkdirSync: mkdirSync28 } = __require("node:fs");
14236
+ const { readFileSync: readFileSync43, writeFileSync: writeFileSync28, existsSync: existsSync55, mkdirSync: mkdirSync29 } = __require("node:fs");
14237
14237
  const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
14238
14238
  const storeFile = join23(metaDir, "store.json");
14239
- if (!existsSync54(storeFile))
14239
+ if (!existsSync55(storeFile))
14240
14240
  return;
14241
14241
  let store = [];
14242
14242
  try {
14243
- store = JSON.parse(readFileSync42(storeFile, "utf8"));
14243
+ store = JSON.parse(readFileSync43(storeFile, "utf8"));
14244
14244
  } catch {
14245
14245
  return;
14246
14246
  }
@@ -14264,8 +14264,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
14264
14264
  updated = true;
14265
14265
  }
14266
14266
  if (updated) {
14267
- mkdirSync28(metaDir, { recursive: true });
14268
- writeFileSync27(storeFile, JSON.stringify(store, null, 2));
14267
+ mkdirSync29(metaDir, { recursive: true });
14268
+ writeFileSync28(storeFile, JSON.stringify(store, null, 2));
14269
14269
  }
14270
14270
  }
14271
14271
  // ── Storage ──────────────────────────────────────────────────────────
@@ -14687,13 +14687,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14687
14687
  // Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
14688
14688
  /** Retrieve top-K strategies for context injection. Returns "" if none. */
14689
14689
  getRelevantStrategiesSync(k = 3, taskType) {
14690
- const { readFileSync: readFileSync42, existsSync: existsSync54 } = __require("node:fs");
14690
+ const { readFileSync: readFileSync43, existsSync: existsSync55 } = __require("node:fs");
14691
14691
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14692
- if (!existsSync54(archiveFile))
14692
+ if (!existsSync55(archiveFile))
14693
14693
  return "";
14694
14694
  let variants = [];
14695
14695
  try {
14696
- variants = JSON.parse(readFileSync42(archiveFile, "utf8"));
14696
+ variants = JSON.parse(readFileSync43(archiveFile, "utf8"));
14697
14697
  } catch {
14698
14698
  return "";
14699
14699
  }
@@ -14711,13 +14711,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14711
14711
  }
14712
14712
  /** Archive a strategy variant synchronously (for task completion path) */
14713
14713
  archiveVariantSync(strategy, outcome, tags = []) {
14714
- const { readFileSync: readFileSync42, writeFileSync: writeFileSync27, existsSync: existsSync54, mkdirSync: mkdirSync28 } = __require("node:fs");
14714
+ const { readFileSync: readFileSync43, writeFileSync: writeFileSync28, existsSync: existsSync55, mkdirSync: mkdirSync29 } = __require("node:fs");
14715
14715
  const dir = join25(this.cwd, ".oa", "arche");
14716
14716
  const archiveFile = join25(dir, "variants.json");
14717
14717
  let variants = [];
14718
14718
  try {
14719
- if (existsSync54(archiveFile))
14720
- variants = JSON.parse(readFileSync42(archiveFile, "utf8"));
14719
+ if (existsSync55(archiveFile))
14720
+ variants = JSON.parse(readFileSync43(archiveFile, "utf8"));
14721
14721
  } catch {
14722
14722
  }
14723
14723
  variants.push({
@@ -14732,8 +14732,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
14732
14732
  });
14733
14733
  if (variants.length > 50)
14734
14734
  variants = variants.slice(-50);
14735
- mkdirSync28(dir, { recursive: true });
14736
- writeFileSync27(archiveFile, JSON.stringify(variants, null, 2));
14735
+ mkdirSync29(dir, { recursive: true });
14736
+ writeFileSync28(archiveFile, JSON.stringify(variants, null, 2));
14737
14737
  }
14738
14738
  async saveArchive(variants) {
14739
14739
  const dir = join25(this.cwd, ".oa", "arche");
@@ -27091,10 +27091,10 @@ ${marker}` : marker);
27091
27091
  if (!this._workingDirectory)
27092
27092
  return;
27093
27093
  try {
27094
- const { mkdirSync: mkdirSync28, writeFileSync: writeFileSync27 } = __require("node:fs");
27095
- const { join: join74 } = __require("node:path");
27096
- const sessionDir = join74(this._workingDirectory, ".oa", "session", this._sessionId);
27097
- mkdirSync28(sessionDir, { recursive: true });
27094
+ const { mkdirSync: mkdirSync29, writeFileSync: writeFileSync28 } = __require("node:fs");
27095
+ const { join: join75 } = __require("node:path");
27096
+ const sessionDir = join75(this._workingDirectory, ".oa", "session", this._sessionId);
27097
+ mkdirSync29(sessionDir, { recursive: true });
27098
27098
  const checkpoint = {
27099
27099
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
27100
27100
  sessionId: this._sessionId,
@@ -27106,7 +27106,7 @@ ${marker}` : marker);
27106
27106
  memexEntryCount: this._memexArchive.size,
27107
27107
  fileRegistrySize: this._fileRegistry.size
27108
27108
  };
27109
- writeFileSync27(join74(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27109
+ writeFileSync28(join75(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
27110
27110
  } catch {
27111
27111
  }
27112
27112
  }
@@ -30061,8 +30061,8 @@ var init_listen = __esm({
30061
30061
  const nvmBase = join48(homedir11(), ".nvm", "versions", "node");
30062
30062
  if (existsSync32(nvmBase)) {
30063
30063
  try {
30064
- const { readdirSync: readdirSync22 } = await import("node:fs");
30065
- for (const ver of readdirSync22(nvmBase)) {
30064
+ const { readdirSync: readdirSync23 } = await import("node:fs");
30065
+ for (const ver of readdirSync23(nvmBase)) {
30066
30066
  const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
30067
30067
  if (existsSync32(join48(tcPath, "dist", "index.js"))) {
30068
30068
  const { createRequire: createRequire5 } = await import("node:module");
@@ -32600,7 +32600,7 @@ var require_websocket = __commonJS({
32600
32600
  var http2 = __require("http");
32601
32601
  var net = __require("net");
32602
32602
  var tls = __require("tls");
32603
- var { randomBytes: randomBytes17, createHash: createHash6 } = __require("crypto");
32603
+ var { randomBytes: randomBytes18, createHash: createHash7 } = __require("crypto");
32604
32604
  var { Duplex, Readable } = __require("stream");
32605
32605
  var { URL: URL3 } = __require("url");
32606
32606
  var PerMessageDeflate = require_permessage_deflate();
@@ -33130,7 +33130,7 @@ var require_websocket = __commonJS({
33130
33130
  }
33131
33131
  }
33132
33132
  const defaultPort = isSecure ? 443 : 80;
33133
- const key = randomBytes17(16).toString("base64");
33133
+ const key = randomBytes18(16).toString("base64");
33134
33134
  const request2 = isSecure ? https.request : http2.request;
33135
33135
  const protocolSet = /* @__PURE__ */ new Set();
33136
33136
  let perMessageDeflate;
@@ -33260,7 +33260,7 @@ var require_websocket = __commonJS({
33260
33260
  abortHandshake(websocket, socket, "Invalid Upgrade header");
33261
33261
  return;
33262
33262
  }
33263
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
33263
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
33264
33264
  if (res.headers["sec-websocket-accept"] !== digest) {
33265
33265
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
33266
33266
  return;
@@ -33627,7 +33627,7 @@ var require_websocket_server = __commonJS({
33627
33627
  var EventEmitter7 = __require("events");
33628
33628
  var http2 = __require("http");
33629
33629
  var { Duplex } = __require("stream");
33630
- var { createHash: createHash6 } = __require("crypto");
33630
+ var { createHash: createHash7 } = __require("crypto");
33631
33631
  var extension = require_extension();
33632
33632
  var PerMessageDeflate = require_permessage_deflate();
33633
33633
  var subprotocol = require_subprotocol();
@@ -33928,7 +33928,7 @@ var require_websocket_server = __commonJS({
33928
33928
  );
33929
33929
  }
33930
33930
  if (this._state > RUNNING) return abortHandshake(socket, 503);
33931
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
33931
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
33932
33932
  const headers = [
33933
33933
  "HTTP/1.1 101 Switching Protocols",
33934
33934
  "Upgrade: websocket",
@@ -38470,26 +38470,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
38470
38470
  async function fetchPeerModels(peerId, authKey) {
38471
38471
  try {
38472
38472
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
38473
- const { existsSync: existsSync54, readFileSync: readFileSync42 } = await import("node:fs");
38474
- const { join: join74 } = await import("node:path");
38473
+ const { existsSync: existsSync55, readFileSync: readFileSync43 } = await import("node:fs");
38474
+ const { join: join75 } = await import("node:path");
38475
38475
  const cwd4 = process.cwd();
38476
38476
  const nexusTool = new NexusTool2(cwd4);
38477
38477
  const nexusDir = nexusTool.getNexusDir();
38478
38478
  let isLocalPeer = false;
38479
38479
  try {
38480
- const statusPath = join74(nexusDir, "status.json");
38481
- if (existsSync54(statusPath)) {
38482
- const status = JSON.parse(readFileSync42(statusPath, "utf8"));
38480
+ const statusPath = join75(nexusDir, "status.json");
38481
+ if (existsSync55(statusPath)) {
38482
+ const status = JSON.parse(readFileSync43(statusPath, "utf8"));
38483
38483
  if (status.peerId === peerId)
38484
38484
  isLocalPeer = true;
38485
38485
  }
38486
38486
  } catch {
38487
38487
  }
38488
38488
  if (isLocalPeer) {
38489
- const pricingPath = join74(nexusDir, "pricing.json");
38490
- if (existsSync54(pricingPath)) {
38489
+ const pricingPath = join75(nexusDir, "pricing.json");
38490
+ if (existsSync55(pricingPath)) {
38491
38491
  try {
38492
- const pricing = JSON.parse(readFileSync42(pricingPath, "utf8"));
38492
+ const pricing = JSON.parse(readFileSync43(pricingPath, "utf8"));
38493
38493
  const localModels = (pricing.models || []).map((m) => ({
38494
38494
  name: m.model || "unknown",
38495
38495
  size: m.parameterSize || "",
@@ -38503,10 +38503,10 @@ async function fetchPeerModels(peerId, authKey) {
38503
38503
  }
38504
38504
  }
38505
38505
  }
38506
- const cachePath = join74(nexusDir, "peer-models-cache.json");
38507
- if (existsSync54(cachePath)) {
38506
+ const cachePath = join75(nexusDir, "peer-models-cache.json");
38507
+ if (existsSync55(cachePath)) {
38508
38508
  try {
38509
- const cache4 = JSON.parse(readFileSync42(cachePath, "utf8"));
38509
+ const cache4 = JSON.parse(readFileSync43(cachePath, "utf8"));
38510
38510
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
38511
38511
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
38512
38512
  if (age < 5 * 60 * 1e3) {
@@ -38621,10 +38621,10 @@ async function fetchPeerModels(peerId, authKey) {
38621
38621
  } catch {
38622
38622
  }
38623
38623
  if (isLocalPeer) {
38624
- const pricingPath = join74(nexusDir, "pricing.json");
38625
- if (existsSync54(pricingPath)) {
38624
+ const pricingPath = join75(nexusDir, "pricing.json");
38625
+ if (existsSync55(pricingPath)) {
38626
38626
  try {
38627
- const pricing = JSON.parse(readFileSync42(pricingPath, "utf8"));
38627
+ const pricing = JSON.parse(readFileSync43(pricingPath, "utf8"));
38628
38628
  return (pricing.models || []).map((m) => ({
38629
38629
  name: m.model || "unknown",
38630
38630
  size: m.parameterSize || "",
@@ -46928,9 +46928,9 @@ async function handleSlashCommand(input, ctx) {
46928
46928
  renderInfo("No wallet configured. Ask the agent to create one via the nexus tool.");
46929
46929
  }
46930
46930
  } else if (sub === "name") {
46931
- const { homedir: homedir19 } = __require("node:os");
46931
+ const { homedir: homedir20 } = __require("node:os");
46932
46932
  const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
46933
- const namePath = __require("node:path").join(homedir19(), ".open-agents", "agent-name");
46933
+ const namePath = __require("node:path").join(homedir20(), ".open-agents", "agent-name");
46934
46934
  if (rest2) {
46935
46935
  const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
46936
46936
  if (!customName) {
@@ -48240,8 +48240,8 @@ async function handleSlashCommand(input, ctx) {
48240
48240
  let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
48241
48241
  if (!sponsorName || sponsorName.length < 2) {
48242
48242
  try {
48243
- const { homedir: homedir19 } = __require("os");
48244
- const namePath = __require("path").join(homedir19(), ".open-agents", "agent-name");
48243
+ const { homedir: homedir20 } = __require("os");
48244
+ const namePath = __require("path").join(homedir20(), ".open-agents", "agent-name");
48245
48245
  if (existsSync42(namePath))
48246
48246
  sponsorName = readFileSync31(namePath, "utf8").trim();
48247
48247
  } catch {
@@ -49621,12 +49621,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
49621
49621
  continue;
49622
49622
  }
49623
49623
  const { basename: basename18, join: pathJoin } = await import("node:path");
49624
- const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync28, existsSync: exists } = await import("node:fs");
49625
- const { homedir: homedir19 } = await import("node:os");
49624
+ const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync29, existsSync: exists } = await import("node:fs");
49625
+ const { homedir: homedir20 } = await import("node:os");
49626
49626
  const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
49627
- const destDir = pathJoin(homedir19(), ".open-agents", "voice", "models", modelName);
49627
+ const destDir = pathJoin(homedir20(), ".open-agents", "voice", "models", modelName);
49628
49628
  if (!exists(destDir))
49629
- mkdirSync28(destDir, { recursive: true });
49629
+ mkdirSync29(destDir, { recursive: true });
49630
49630
  copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
49631
49631
  copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
49632
49632
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -50304,11 +50304,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
50304
50304
  const models = await fetchModels(peerUrl, authKey);
50305
50305
  if (models.length > 0) {
50306
50306
  try {
50307
- const { writeFileSync: writeFileSync27, mkdirSync: mkdirSync28 } = await import("node:fs");
50308
- const { join: join74, dirname: dirname23 } = await import("node:path");
50309
- const cachePath = join74(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
50310
- mkdirSync28(dirname23(cachePath), { recursive: true });
50311
- writeFileSync27(cachePath, JSON.stringify({
50307
+ const { writeFileSync: writeFileSync28, mkdirSync: mkdirSync29 } = await import("node:fs");
50308
+ const { join: join75, dirname: dirname23 } = await import("node:path");
50309
+ const cachePath = join75(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
50310
+ mkdirSync29(dirname23(cachePath), { recursive: true });
50311
+ writeFileSync28(cachePath, JSON.stringify({
50312
50312
  peerId,
50313
50313
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
50314
50314
  models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
@@ -50507,17 +50507,17 @@ async function handleUpdate(subcommand, ctx) {
50507
50507
  try {
50508
50508
  const { createRequire: createRequire5 } = await import("node:module");
50509
50509
  const { fileURLToPath: fileURLToPath15 } = await import("node:url");
50510
- const { dirname: dirname23, join: join74 } = await import("node:path");
50511
- const { existsSync: existsSync54 } = await import("node:fs");
50510
+ const { dirname: dirname23, join: join75 } = await import("node:path");
50511
+ const { existsSync: existsSync55 } = await import("node:fs");
50512
50512
  const req = createRequire5(import.meta.url);
50513
50513
  const thisDir = dirname23(fileURLToPath15(import.meta.url));
50514
50514
  const candidates = [
50515
- join74(thisDir, "..", "package.json"),
50516
- join74(thisDir, "..", "..", "package.json"),
50517
- join74(thisDir, "..", "..", "..", "package.json")
50515
+ join75(thisDir, "..", "package.json"),
50516
+ join75(thisDir, "..", "..", "package.json"),
50517
+ join75(thisDir, "..", "..", "..", "package.json")
50518
50518
  ];
50519
50519
  for (const pkgPath of candidates) {
50520
- if (existsSync54(pkgPath)) {
50520
+ if (existsSync55(pkgPath)) {
50521
50521
  const pkg = req(pkgPath);
50522
50522
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
50523
50523
  currentVersion = pkg.version ?? "0.0.0";
@@ -61592,6 +61592,173 @@ var init_mouse_filter = __esm({
61592
61592
  }
61593
61593
  });
61594
61594
 
61595
+ // packages/cli/dist/api/profiles.js
61596
+ import { existsSync as existsSync50, readFileSync as readFileSync39, writeFileSync as writeFileSync23, mkdirSync as mkdirSync24, readdirSync as readdirSync19, unlinkSync as unlinkSync12 } from "node:fs";
61597
+ import { join as join67 } from "node:path";
61598
+ import { homedir as homedir17 } from "node:os";
61599
+ import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
61600
+ function globalProfileDir() {
61601
+ return join67(homedir17(), ".open-agents", "profiles");
61602
+ }
61603
+ function projectProfileDir(projectDir) {
61604
+ return join67(projectDir || process.cwd(), ".oa", "profiles");
61605
+ }
61606
+ function listProfiles(projectDir) {
61607
+ const result = [];
61608
+ const seen = /* @__PURE__ */ new Set();
61609
+ const projDir = projectProfileDir(projectDir);
61610
+ if (existsSync50(projDir)) {
61611
+ for (const f of readdirSync19(projDir).filter((f2) => f2.endsWith(".json"))) {
61612
+ try {
61613
+ const raw = JSON.parse(readFileSync39(join67(projDir, f), "utf8"));
61614
+ const name = f.replace(".json", "");
61615
+ seen.add(name);
61616
+ result.push({
61617
+ name,
61618
+ description: raw.description || "",
61619
+ encrypted: raw.encrypted === true,
61620
+ source: "project"
61621
+ });
61622
+ } catch {
61623
+ }
61624
+ }
61625
+ }
61626
+ const globDir = globalProfileDir();
61627
+ if (existsSync50(globDir)) {
61628
+ for (const f of readdirSync19(globDir).filter((f2) => f2.endsWith(".json"))) {
61629
+ const name = f.replace(".json", "");
61630
+ if (seen.has(name))
61631
+ continue;
61632
+ try {
61633
+ const raw = JSON.parse(readFileSync39(join67(globDir, f), "utf8"));
61634
+ result.push({
61635
+ name,
61636
+ description: raw.description || "",
61637
+ encrypted: raw.encrypted === true,
61638
+ source: "global"
61639
+ });
61640
+ } catch {
61641
+ }
61642
+ }
61643
+ }
61644
+ return result;
61645
+ }
61646
+ function loadProfile(name, password, projectDir) {
61647
+ const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
61648
+ const projPath = join67(projectProfileDir(projectDir), `${sanitized}.json`);
61649
+ const globPath = join67(globalProfileDir(), `${sanitized}.json`);
61650
+ const filePath = existsSync50(projPath) ? projPath : existsSync50(globPath) ? globPath : null;
61651
+ if (!filePath)
61652
+ return null;
61653
+ const raw = JSON.parse(readFileSync39(filePath, "utf8"));
61654
+ if (raw.encrypted === true) {
61655
+ if (!password)
61656
+ return null;
61657
+ return decryptProfile(raw, password);
61658
+ }
61659
+ return raw;
61660
+ }
61661
+ function saveProfile(profile, password, scope = "global", projectDir) {
61662
+ const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
61663
+ mkdirSync24(dir, { recursive: true });
61664
+ const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
61665
+ const filePath = join67(dir, `${sanitized}.json`);
61666
+ profile.modified = (/* @__PURE__ */ new Date()).toISOString();
61667
+ if (password) {
61668
+ const encrypted = encryptProfile(profile, password);
61669
+ writeFileSync23(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
61670
+ } else {
61671
+ profile.encrypted = false;
61672
+ writeFileSync23(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
61673
+ }
61674
+ }
61675
+ function deleteProfile(name, scope = "global", projectDir) {
61676
+ const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
61677
+ const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
61678
+ const filePath = join67(dir, `${sanitized}.json`);
61679
+ if (existsSync50(filePath)) {
61680
+ unlinkSync12(filePath);
61681
+ return true;
61682
+ }
61683
+ return false;
61684
+ }
61685
+ function encryptProfile(profile, password) {
61686
+ const salt = randomBytes15(32);
61687
+ const key = scryptSync3(password, salt, 32);
61688
+ const iv = randomBytes15(16);
61689
+ const cipher = createCipheriv3("aes-256-gcm", key, iv);
61690
+ const plaintext = JSON.stringify(profile);
61691
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
61692
+ const tag = cipher.getAuthTag();
61693
+ return {
61694
+ encrypted: true,
61695
+ iv: iv.toString("hex"),
61696
+ salt: salt.toString("hex"),
61697
+ data: encrypted.toString("hex"),
61698
+ tag: tag.toString("hex"),
61699
+ name: profile.name,
61700
+ description: profile.description
61701
+ };
61702
+ }
61703
+ function decryptProfile(enc, password) {
61704
+ try {
61705
+ const salt = Buffer.from(enc.salt, "hex");
61706
+ const key = scryptSync3(password, salt, 32);
61707
+ const iv = Buffer.from(enc.iv, "hex");
61708
+ const decipher = createDecipheriv3("aes-256-gcm", key, iv);
61709
+ decipher.setAuthTag(Buffer.from(enc.tag, "hex"));
61710
+ const decrypted = Buffer.concat([
61711
+ decipher.update(Buffer.from(enc.data, "hex")),
61712
+ decipher.final()
61713
+ ]);
61714
+ return JSON.parse(decrypted.toString("utf8"));
61715
+ } catch {
61716
+ return null;
61717
+ }
61718
+ }
61719
+ var PRESET_PROFILES;
61720
+ var init_profiles = __esm({
61721
+ "packages/cli/dist/api/profiles.js"() {
61722
+ "use strict";
61723
+ PRESET_PROFILES = {
61724
+ "readonly": {
61725
+ name: "readonly",
61726
+ description: "Read-only \u2014 no file writes, no shell mutations",
61727
+ tools: {
61728
+ deny: ["file_write", "file_edit", "file_patch", "batch_edit", "shell"],
61729
+ shell_deny: ["rm", "sudo", "chmod", "chown", "mv", "cp", "mkdir", "rmdir", "touch"]
61730
+ },
61731
+ commands: { deny: ["destroy", "update", "sponsor", "expose"] },
61732
+ limits: { max_turns: 10, timeout_s: 300 },
61733
+ encrypted: false,
61734
+ created: "2026-03-25T00:00:00Z"
61735
+ },
61736
+ "ci-safe": {
61737
+ name: "ci-safe",
61738
+ description: "CI/CD \u2014 can read, test, lint, but not write production files",
61739
+ tools: {
61740
+ allow: ["file_read", "grep_search", "glob_find", "list_directory", "shell", "task_complete"],
61741
+ shell_allow: ["npm test", "npm run", "npx tsc", "npx eslint", "cat", "grep", "find", "wc", "head", "tail"],
61742
+ shell_deny: ["rm -rf", "sudo", "chmod", "dd", "mkfs", "curl", "wget"]
61743
+ },
61744
+ commands: { allow: ["help", "stats", "tools", "config"] },
61745
+ limits: { max_turns: 15, timeout_s: 600 },
61746
+ encrypted: false,
61747
+ created: "2026-03-25T00:00:00Z"
61748
+ },
61749
+ "full": {
61750
+ name: "full",
61751
+ description: "Full access \u2014 no restrictions",
61752
+ tools: {},
61753
+ commands: {},
61754
+ limits: {},
61755
+ encrypted: false,
61756
+ created: "2026-03-25T00:00:00Z"
61757
+ }
61758
+ };
61759
+ }
61760
+ });
61761
+
61595
61762
  // packages/cli/dist/api/serve.js
61596
61763
  var serve_exports = {};
61597
61764
  __export(serve_exports, {
@@ -61601,14 +61768,14 @@ __export(serve_exports, {
61601
61768
  import * as http from "node:http";
61602
61769
  import { createRequire as createRequire2 } from "node:module";
61603
61770
  import { fileURLToPath as fileURLToPath12 } from "node:url";
61604
- import { dirname as dirname20, join as join67, resolve as resolve31 } from "node:path";
61771
+ import { dirname as dirname20, join as join68, resolve as resolve31 } from "node:path";
61605
61772
  import { spawn as spawn20 } from "node:child_process";
61606
- import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, readFileSync as readFileSync39, readdirSync as readdirSync19, existsSync as existsSync50 } from "node:fs";
61607
- import { randomBytes as randomBytes15 } from "node:crypto";
61773
+ import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync24, readFileSync as readFileSync40, readdirSync as readdirSync20, existsSync as existsSync51 } from "node:fs";
61774
+ import { randomBytes as randomBytes16 } from "node:crypto";
61608
61775
  function getVersion3() {
61609
61776
  try {
61610
61777
  const require2 = createRequire2(import.meta.url);
61611
- const pkgPath = join67(dirname20(fileURLToPath12(import.meta.url)), "..", "..", "package.json");
61778
+ const pkgPath = join68(dirname20(fileURLToPath12(import.meta.url)), "..", "..", "package.json");
61612
61779
  const pkg = require2(pkgPath);
61613
61780
  return pkg.version;
61614
61781
  } catch {
@@ -61738,29 +61905,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
61738
61905
  }
61739
61906
  function jobsDir() {
61740
61907
  const root = resolve31(process.cwd());
61741
- const dir = join67(root, ".oa", "jobs");
61742
- mkdirSync24(dir, { recursive: true });
61908
+ const dir = join68(root, ".oa", "jobs");
61909
+ mkdirSync25(dir, { recursive: true });
61743
61910
  return dir;
61744
61911
  }
61745
61912
  function loadJob(id) {
61746
- const file = join67(jobsDir(), `${id}.json`);
61747
- if (!existsSync50(file))
61913
+ const file = join68(jobsDir(), `${id}.json`);
61914
+ if (!existsSync51(file))
61748
61915
  return null;
61749
61916
  try {
61750
- return JSON.parse(readFileSync39(file, "utf-8"));
61917
+ return JSON.parse(readFileSync40(file, "utf-8"));
61751
61918
  } catch {
61752
61919
  return null;
61753
61920
  }
61754
61921
  }
61755
61922
  function listJobs() {
61756
61923
  const dir = jobsDir();
61757
- if (!existsSync50(dir))
61924
+ if (!existsSync51(dir))
61758
61925
  return [];
61759
- const files = readdirSync19(dir).filter((f) => f.endsWith(".json")).sort();
61926
+ const files = readdirSync20(dir).filter((f) => f.endsWith(".json")).sort();
61760
61927
  const jobs = [];
61761
61928
  for (const file of files) {
61762
61929
  try {
61763
- jobs.push(JSON.parse(readFileSync39(join67(dir, file), "utf-8")));
61930
+ jobs.push(JSON.parse(readFileSync40(join68(dir, file), "utf-8")));
61764
61931
  } catch {
61765
61932
  }
61766
61933
  }
@@ -61887,7 +62054,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
61887
62054
  "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
61888
62055
  "Access-Control-Allow-Headers": "Content-Type, Authorization"
61889
62056
  });
61890
- const chatId = `chatcmpl-${randomBytes15(12).toString("hex")}`;
62057
+ const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
61891
62058
  let buffer = "";
61892
62059
  ollamaStream(ollamaUrl, "/api/chat", "POST", ollamaPayload, (chunk) => {
61893
62060
  buffer += chunk;
@@ -61992,7 +62159,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
61992
62159
  metrics.totalTokensOut += ollamaResp.eval_count;
61993
62160
  if (ollamaResp.prompt_eval_count)
61994
62161
  metrics.totalTokensIn += ollamaResp.prompt_eval_count;
61995
- const chatId = `chatcmpl-${randomBytes15(12).toString("hex")}`;
62162
+ const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
61996
62163
  const openaiResponse = {
61997
62164
  id: chatId,
61998
62165
  object: "chat.completion",
@@ -62075,7 +62242,7 @@ async function handleV1Run(req, res) {
62075
62242
  jsonResponse(res, 400, { error: "Missing required field: task" });
62076
62243
  return;
62077
62244
  }
62078
- const id = `job-${randomBytes15(3).toString("hex")}`;
62245
+ const id = `job-${randomBytes16(3).toString("hex")}`;
62079
62246
  const dir = jobsDir();
62080
62247
  const workingDir = requestBody["working_directory"] || req.headers["x-working-directory"];
62081
62248
  const isolate = requestBody["isolate"] === true;
@@ -62083,8 +62250,8 @@ async function handleV1Run(req, res) {
62083
62250
  if (workingDir) {
62084
62251
  cwd4 = resolve31(workingDir);
62085
62252
  } else if (isolate) {
62086
- const wsDir = join67(dir, "..", "workspaces", id);
62087
- mkdirSync24(wsDir, { recursive: true });
62253
+ const wsDir = join68(dir, "..", "workspaces", id);
62254
+ mkdirSync25(wsDir, { recursive: true });
62088
62255
  cwd4 = wsDir;
62089
62256
  } else {
62090
62257
  cwd4 = resolve31(process.cwd());
@@ -62113,6 +62280,23 @@ async function handleV1Run(req, res) {
62113
62280
  const timeout = requestBody["timeout_s"];
62114
62281
  if (timeout && timeout > 0)
62115
62282
  args.push("--timeout", String(timeout));
62283
+ const profileName = requestBody["profile"] || req.headers["x-tool-profile"] || void 0;
62284
+ let activeProfile = null;
62285
+ if (profileName) {
62286
+ const profilePassword = req.headers["x-profile-password"];
62287
+ activeProfile = PRESET_PROFILES[profileName] || loadProfile(profileName, profilePassword);
62288
+ if (!activeProfile) {
62289
+ jsonResponse(res, 400, { error: "Profile not found or wrong password", profile: profileName });
62290
+ return;
62291
+ }
62292
+ if (activeProfile.limits.max_turns && !requestBody["max_turns"]) {
62293
+ args.push("--max-turns", String(activeProfile.limits.max_turns));
62294
+ }
62295
+ if (activeProfile.limits.timeout_s && !requestBody["timeout_s"]) {
62296
+ args.push("--timeout", String(activeProfile.limits.timeout_s));
62297
+ }
62298
+ }
62299
+ job.profile = profileName || null;
62116
62300
  const runEnv = {
62117
62301
  ...process.env,
62118
62302
  OA_JOB_ID: id,
@@ -62120,6 +62304,9 @@ async function handleV1Run(req, res) {
62120
62304
  OA_RUN_USER: authUser,
62121
62305
  OA_RUN_SCOPE: authScope
62122
62306
  };
62307
+ if (activeProfile) {
62308
+ runEnv["OA_TOOL_PROFILE"] = JSON.stringify(activeProfile);
62309
+ }
62123
62310
  const customEnv = requestBody["env"];
62124
62311
  if (customEnv && typeof customEnv === "object") {
62125
62312
  for (const [k, v] of Object.entries(customEnv)) {
@@ -62136,7 +62323,7 @@ async function handleV1Run(req, res) {
62136
62323
  });
62137
62324
  child.unref();
62138
62325
  job.pid = child.pid ?? 0;
62139
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
62326
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
62140
62327
  runningProcesses.set(id, child);
62141
62328
  if (streamMode) {
62142
62329
  res.writeHead(200, {
@@ -62166,7 +62353,7 @@ async function handleV1Run(req, res) {
62166
62353
  job.status = code === 0 ? "completed" : "failed";
62167
62354
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
62168
62355
  try {
62169
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
62356
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
62170
62357
  } catch {
62171
62358
  }
62172
62359
  runningProcesses.delete(id);
@@ -62197,7 +62384,7 @@ async function handleV1Run(req, res) {
62197
62384
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
62198
62385
  }
62199
62386
  try {
62200
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
62387
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
62201
62388
  } catch {
62202
62389
  }
62203
62390
  runningProcesses.delete(id);
@@ -62238,7 +62425,7 @@ function handleV1RunsDelete(res, id) {
62238
62425
  job.error = "Aborted via API";
62239
62426
  const dir = jobsDir();
62240
62427
  try {
62241
- writeFileSync23(join67(dir, `${id}.json`), JSON.stringify(job, null, 2));
62428
+ writeFileSync24(join68(dir, `${id}.json`), JSON.stringify(job, null, 2));
62242
62429
  } catch {
62243
62430
  }
62244
62431
  runningProcesses.delete(id);
@@ -62486,6 +62673,74 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
62486
62673
  await handlePostCommand(res, cmd);
62487
62674
  return;
62488
62675
  }
62676
+ if (pathname === "/v1/profiles" && method === "GET") {
62677
+ const profiles = listProfiles();
62678
+ const presets = Object.values(PRESET_PROFILES).map((p) => ({ name: p.name, description: p.description, encrypted: false, source: "preset" }));
62679
+ jsonResponse(res, 200, { profiles: [...presets, ...profiles] });
62680
+ return;
62681
+ }
62682
+ const profileGetMatch = pathname.match(/^\/v1\/profiles\/([a-zA-Z0-9_-]+)$/);
62683
+ if (profileGetMatch && method === "GET") {
62684
+ const name = profileGetMatch[1];
62685
+ const password = req.headers["x-profile-password"];
62686
+ if (PRESET_PROFILES[name]) {
62687
+ jsonResponse(res, 200, { profile: PRESET_PROFILES[name] });
62688
+ return;
62689
+ }
62690
+ const profile = loadProfile(name, password);
62691
+ if (profile) {
62692
+ jsonResponse(res, 200, { profile });
62693
+ } else {
62694
+ jsonResponse(res, 404, { error: "Profile not found or wrong password", name });
62695
+ }
62696
+ return;
62697
+ }
62698
+ if (pathname === "/v1/profiles" && method === "POST") {
62699
+ if (!checkAuth(req, res, "admin")) {
62700
+ status = 403;
62701
+ return;
62702
+ }
62703
+ const body = await parseJsonBody(req);
62704
+ if (!body || typeof body !== "object") {
62705
+ jsonResponse(res, 400, { error: "Invalid JSON body" });
62706
+ return;
62707
+ }
62708
+ const b = body;
62709
+ const name = b["name"];
62710
+ if (!name || typeof name !== "string") {
62711
+ jsonResponse(res, 400, { error: "Profile 'name' required" });
62712
+ return;
62713
+ }
62714
+ const profile = {
62715
+ name: name.replace(/[^a-zA-Z0-9_-]/g, ""),
62716
+ description: b["description"] || "",
62717
+ tools: b["tools"] || {},
62718
+ commands: b["commands"] || {},
62719
+ limits: b["limits"] || {},
62720
+ encrypted: false,
62721
+ created: (/* @__PURE__ */ new Date()).toISOString()
62722
+ };
62723
+ const password = b["password"] || req.headers["x-profile-password"] || void 0;
62724
+ const scope = b["scope"] || "global";
62725
+ saveProfile(profile, password, scope);
62726
+ jsonResponse(res, 201, { status: "created", name: profile.name, encrypted: !!password, scope });
62727
+ return;
62728
+ }
62729
+ const profileDelMatch = pathname.match(/^\/v1\/profiles\/([a-zA-Z0-9_-]+)$/);
62730
+ if (profileDelMatch && method === "DELETE") {
62731
+ if (!checkAuth(req, res, "admin")) {
62732
+ status = 403;
62733
+ return;
62734
+ }
62735
+ const name = profileDelMatch[1];
62736
+ if (PRESET_PROFILES[name]) {
62737
+ jsonResponse(res, 400, { error: "Cannot delete preset profiles" });
62738
+ return;
62739
+ }
62740
+ const deleted = deleteProfile(name, "global") || deleteProfile(name, "project");
62741
+ jsonResponse(res, deleted ? 200 : 404, deleted ? { status: "deleted", name } : { error: "Profile not found", name });
62742
+ return;
62743
+ }
62489
62744
  status = 404;
62490
62745
  jsonResponse(res, 404, { error: "Not found", path: pathname });
62491
62746
  } catch (err) {
@@ -62533,6 +62788,15 @@ function startApiServer(options = {}) {
62533
62788
  }
62534
62789
  });
62535
62790
  });
62791
+ server.on("error", (err) => {
62792
+ if (err.code === "EADDRINUSE") {
62793
+ process.stderr.write(` Port ${port} already in use \u2014 API server not started.
62794
+ `);
62795
+ } else {
62796
+ process.stderr.write(` API server error: ${err.message}
62797
+ `);
62798
+ }
62799
+ });
62536
62800
  server.listen(port, host, () => {
62537
62801
  const version = getVersion3();
62538
62802
  process.stderr.write(`
@@ -62591,6 +62855,7 @@ var init_serve = __esm({
62591
62855
  init_config();
62592
62856
  init_oa_directory();
62593
62857
  init_render();
62858
+ init_profiles();
62594
62859
  metrics = {
62595
62860
  requests: /* @__PURE__ */ new Map(),
62596
62861
  totalTokensIn: 0,
@@ -62606,13 +62871,13 @@ var init_serve = __esm({
62606
62871
  import * as readline2 from "node:readline";
62607
62872
  import { Writable } from "node:stream";
62608
62873
  import { cwd } from "node:process";
62609
- import { resolve as resolve32, join as join68, dirname as dirname21, extname as extname11 } from "node:path";
62874
+ import { resolve as resolve32, join as join69, dirname as dirname21, extname as extname11 } from "node:path";
62610
62875
  import { createRequire as createRequire3 } from "node:module";
62611
62876
  import { fileURLToPath as fileURLToPath13 } from "node:url";
62612
- import { readFileSync as readFileSync40, writeFileSync as writeFileSync24, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync20, mkdirSync as mkdirSync25 } from "node:fs";
62613
- import { existsSync as existsSync51 } from "node:fs";
62877
+ import { readFileSync as readFileSync41, writeFileSync as writeFileSync25, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync21, mkdirSync as mkdirSync26 } from "node:fs";
62878
+ import { existsSync as existsSync52 } from "node:fs";
62614
62879
  import { execSync as execSync33 } from "node:child_process";
62615
- import { homedir as homedir17 } from "node:os";
62880
+ import { homedir as homedir18 } from "node:os";
62616
62881
  function formatTimeAgo(date) {
62617
62882
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
62618
62883
  if (seconds < 60)
@@ -62631,12 +62896,12 @@ function getVersion4() {
62631
62896
  const require2 = createRequire3(import.meta.url);
62632
62897
  const thisDir = dirname21(fileURLToPath13(import.meta.url));
62633
62898
  const candidates = [
62634
- join68(thisDir, "..", "package.json"),
62635
- join68(thisDir, "..", "..", "package.json"),
62636
- join68(thisDir, "..", "..", "..", "package.json")
62899
+ join69(thisDir, "..", "package.json"),
62900
+ join69(thisDir, "..", "..", "package.json"),
62901
+ join69(thisDir, "..", "..", "..", "package.json")
62637
62902
  ];
62638
62903
  for (const pkgPath of candidates) {
62639
- if (existsSync51(pkgPath)) {
62904
+ if (existsSync52(pkgPath)) {
62640
62905
  const pkg = require2(pkgPath);
62641
62906
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
62642
62907
  return pkg.version ?? "0.0.0";
@@ -62871,15 +63136,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
62871
63136
  function gatherMemorySnippets(root) {
62872
63137
  const snippets = [];
62873
63138
  const dirs = [
62874
- join68(root, ".oa", "memory"),
62875
- join68(root, ".open-agents", "memory")
63139
+ join69(root, ".oa", "memory"),
63140
+ join69(root, ".open-agents", "memory")
62876
63141
  ];
62877
63142
  for (const dir of dirs) {
62878
- if (!existsSync51(dir))
63143
+ if (!existsSync52(dir))
62879
63144
  continue;
62880
63145
  try {
62881
- for (const f of readdirSync20(dir).filter((f2) => f2.endsWith(".json"))) {
62882
- const data = JSON.parse(readFileSync40(join68(dir, f), "utf-8"));
63146
+ for (const f of readdirSync21(dir).filter((f2) => f2.endsWith(".json"))) {
63147
+ const data = JSON.parse(readFileSync41(join69(dir, f), "utf-8"));
62883
63148
  for (const val of Object.values(data)) {
62884
63149
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
62885
63150
  if (v.length > 10)
@@ -63036,9 +63301,9 @@ ${metabolismMemories}
63036
63301
  } catch {
63037
63302
  }
63038
63303
  try {
63039
- const archeFile = join68(repoRoot, ".oa", "arche", "variants.json");
63040
- if (existsSync51(archeFile)) {
63041
- const variants = JSON.parse(readFileSync40(archeFile, "utf8"));
63304
+ const archeFile = join69(repoRoot, ".oa", "arche", "variants.json");
63305
+ if (existsSync52(archeFile)) {
63306
+ const variants = JSON.parse(readFileSync41(archeFile, "utf8"));
63042
63307
  if (variants.length > 0) {
63043
63308
  let filtered = variants;
63044
63309
  if (taskType) {
@@ -63175,9 +63440,9 @@ ${lines.join("\n")}
63175
63440
  const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
63176
63441
  let identityInjection = "";
63177
63442
  try {
63178
- const ikStateFile = join68(repoRoot, ".oa", "identity", "self-state.json");
63179
- if (existsSync51(ikStateFile)) {
63180
- const selfState = JSON.parse(readFileSync40(ikStateFile, "utf8"));
63443
+ const ikStateFile = join69(repoRoot, ".oa", "identity", "self-state.json");
63444
+ if (existsSync52(ikStateFile)) {
63445
+ const selfState = JSON.parse(readFileSync41(ikStateFile, "utf8"));
63181
63446
  const lines = [
63182
63447
  `[Identity State v${selfState.version}]`,
63183
63448
  `Self: ${selfState.narrative_summary}`,
@@ -63818,13 +64083,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
63818
64083
  });
63819
64084
  }
63820
64085
  try {
63821
- const ikDir = join68(repoRoot, ".oa", "identity");
63822
- const ikFile = join68(ikDir, "self-state.json");
64086
+ const ikDir = join69(repoRoot, ".oa", "identity");
64087
+ const ikFile = join69(ikDir, "self-state.json");
63823
64088
  let ikState;
63824
- if (existsSync51(ikFile)) {
63825
- ikState = JSON.parse(readFileSync40(ikFile, "utf8"));
64089
+ if (existsSync52(ikFile)) {
64090
+ ikState = JSON.parse(readFileSync41(ikFile, "utf8"));
63826
64091
  } else {
63827
- mkdirSync25(ikDir, { recursive: true });
64092
+ mkdirSync26(ikDir, { recursive: true });
63828
64093
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
63829
64094
  ikState = {
63830
64095
  self_id: `oa-${machineId}`,
@@ -63850,7 +64115,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
63850
64115
  }
63851
64116
  ikState.session_count = (ikState.session_count || 0) + 1;
63852
64117
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
63853
- writeFileSync24(ikFile, JSON.stringify(ikState, null, 2));
64118
+ writeFileSync25(ikFile, JSON.stringify(ikState, null, 2));
63854
64119
  } catch (ikErr) {
63855
64120
  try {
63856
64121
  console.error("[IK-OBSERVE]", ikErr);
@@ -63865,14 +64130,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
63865
64130
  } else {
63866
64131
  renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
63867
64132
  try {
63868
- const ikFile = join68(repoRoot, ".oa", "identity", "self-state.json");
63869
- if (existsSync51(ikFile)) {
63870
- const ikState = JSON.parse(readFileSync40(ikFile, "utf8"));
64133
+ const ikFile = join69(repoRoot, ".oa", "identity", "self-state.json");
64134
+ if (existsSync52(ikFile)) {
64135
+ const ikState = JSON.parse(readFileSync41(ikFile, "utf8"));
63871
64136
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
63872
64137
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
63873
64138
  ikState.session_count = (ikState.session_count || 0) + 1;
63874
64139
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
63875
- writeFileSync24(ikFile, JSON.stringify(ikState, null, 2));
64140
+ writeFileSync25(ikFile, JSON.stringify(ikState, null, 2));
63876
64141
  }
63877
64142
  } catch {
63878
64143
  }
@@ -64215,7 +64480,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
64215
64480
  let p2pGateway = null;
64216
64481
  let peerMesh = null;
64217
64482
  let inferenceRouter = null;
64218
- const secretVault = new SecretVault(join68(repoRoot, ".oa", "vault.enc"));
64483
+ const secretVault = new SecretVault(join69(repoRoot, ".oa", "vault.enc"));
64219
64484
  let adminSessionKey = null;
64220
64485
  const callSubAgents = /* @__PURE__ */ new Map();
64221
64486
  const streamRenderer = new StreamRenderer();
@@ -64436,13 +64701,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
64436
64701
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
64437
64702
  return [hits, line];
64438
64703
  }
64439
- const HISTORY_DIR = join68(homedir17(), ".open-agents");
64440
- const HISTORY_FILE = join68(HISTORY_DIR, "repl-history");
64704
+ const HISTORY_DIR = join69(homedir18(), ".open-agents");
64705
+ const HISTORY_FILE = join69(HISTORY_DIR, "repl-history");
64441
64706
  const MAX_HISTORY_LINES = 500;
64442
64707
  let savedHistory = [];
64443
64708
  try {
64444
- if (existsSync51(HISTORY_FILE)) {
64445
- const raw = readFileSync40(HISTORY_FILE, "utf8").trim();
64709
+ if (existsSync52(HISTORY_FILE)) {
64710
+ const raw = readFileSync41(HISTORY_FILE, "utf8").trim();
64446
64711
  if (raw)
64447
64712
  savedHistory = raw.split("\n").reverse();
64448
64713
  }
@@ -64522,12 +64787,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
64522
64787
  if (!line.trim())
64523
64788
  return;
64524
64789
  try {
64525
- mkdirSync25(HISTORY_DIR, { recursive: true });
64790
+ mkdirSync26(HISTORY_DIR, { recursive: true });
64526
64791
  appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
64527
64792
  if (Math.random() < 0.02) {
64528
- const all = readFileSync40(HISTORY_FILE, "utf8").trim().split("\n");
64793
+ const all = readFileSync41(HISTORY_FILE, "utf8").trim().split("\n");
64529
64794
  if (all.length > MAX_HISTORY_LINES) {
64530
- writeFileSync24(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
64795
+ writeFileSync25(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
64531
64796
  }
64532
64797
  }
64533
64798
  } catch {
@@ -64703,7 +64968,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
64703
64968
  } catch {
64704
64969
  }
64705
64970
  try {
64706
- const oaDir = join68(repoRoot, ".oa");
64971
+ const oaDir = join69(repoRoot, ".oa");
64707
64972
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
64708
64973
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
64709
64974
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -64735,7 +65000,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
64735
65000
  } catch {
64736
65001
  }
64737
65002
  try {
64738
- const oaDir = join68(repoRoot, ".oa");
65003
+ const oaDir = join69(repoRoot, ".oa");
64739
65004
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
64740
65005
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
64741
65006
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -64775,27 +65040,41 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
64775
65040
  } catch {
64776
65041
  }
64777
65042
  try {
64778
- const { startApiServer: startApiServer2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
64779
65043
  const apiPort = parseInt(process.env["OA_PORT"] || "11435", 10);
64780
- const apiServer = startApiServer2({
64781
- port: apiPort,
64782
- ollamaUrl: currentConfig.backendUrl || "http://127.0.0.1:11434"
65044
+ const portFree = await new Promise((resolve36) => {
65045
+ const net = __require("net");
65046
+ const tester = net.createServer();
65047
+ tester.once("error", (err) => {
65048
+ if (err.code === "EADDRINUSE")
65049
+ resolve36(false);
65050
+ else
65051
+ resolve36(true);
65052
+ });
65053
+ tester.once("listening", () => {
65054
+ tester.close(() => resolve36(true));
65055
+ });
65056
+ tester.listen(apiPort, "127.0.0.1");
64783
65057
  });
64784
- writeContent(() => renderInfo(`REST API: http://localhost:${apiPort} (${process.env["OA_API_KEY"] || process.env["OA_API_KEYS"] ? "auth enabled" : "open"})`));
64785
- } catch (apiErr) {
64786
- const msg = apiErr instanceof Error ? apiErr.message : String(apiErr);
64787
- if (msg.includes("EADDRINUSE")) {
65058
+ if (!portFree) {
64788
65059
  } else {
64789
- writeContent(() => renderWarning(`API server: ${msg.slice(0, 60)}`));
65060
+ const { startApiServer: startApiServer2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
65061
+ const apiServer = startApiServer2({
65062
+ port: apiPort,
65063
+ ollamaUrl: currentConfig.backendUrl || "http://127.0.0.1:11434"
65064
+ });
65065
+ apiServer.on?.("error", () => {
65066
+ });
65067
+ writeContent(() => renderInfo(`REST API: http://localhost:${apiPort}`));
64790
65068
  }
65069
+ } catch {
64791
65070
  }
64792
65071
  try {
64793
65072
  const { homedir: _hd } = await import("node:os");
64794
- const globalNamePath = join68(_hd(), ".open-agents", "agent-name");
65073
+ const globalNamePath = join69(_hd(), ".open-agents", "agent-name");
64795
65074
  let agName = "oa-node";
64796
65075
  try {
64797
- if (existsSync51(globalNamePath))
64798
- agName = readFileSync40(globalNamePath, "utf8").trim() || agName;
65076
+ if (existsSync52(globalNamePath))
65077
+ agName = readFileSync41(globalNamePath, "utf8").trim() || agName;
64799
65078
  } catch {
64800
65079
  }
64801
65080
  fetch("https://openagents.nexus/api/v1/directory", {
@@ -65688,7 +65967,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
65688
65967
  kind,
65689
65968
  targetUrl,
65690
65969
  authKey,
65691
- stateDir: join68(repoRoot, ".oa"),
65970
+ stateDir: join69(repoRoot, ".oa"),
65692
65971
  passthrough: passthrough ?? false,
65693
65972
  loadbalance: loadbalance ?? false,
65694
65973
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -65736,7 +66015,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
65736
66015
  await tunnelGateway.stop();
65737
66016
  tunnelGateway = null;
65738
66017
  }
65739
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join68(repoRoot, ".oa") });
66018
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join69(repoRoot, ".oa") });
65740
66019
  newTunnel.on("stats", (stats) => {
65741
66020
  statusBar.setExposeStatus({
65742
66021
  status: stats.status,
@@ -66008,10 +66287,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
66008
66287
  writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
66009
66288
  }
66010
66289
  try {
66011
- const nexusDir = join68(repoRoot, OA_DIR, "nexus");
66012
- const pidFile = join68(nexusDir, "daemon.pid");
66013
- if (existsSync51(pidFile)) {
66014
- const pid = parseInt(readFileSync40(pidFile, "utf8").trim(), 10);
66290
+ const nexusDir = join69(repoRoot, OA_DIR, "nexus");
66291
+ const pidFile = join69(nexusDir, "daemon.pid");
66292
+ if (existsSync52(pidFile)) {
66293
+ const pid = parseInt(readFileSync41(pidFile, "utf8").trim(), 10);
66015
66294
  if (pid > 0) {
66016
66295
  try {
66017
66296
  if (process.platform === "win32") {
@@ -66033,13 +66312,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
66033
66312
  } catch {
66034
66313
  }
66035
66314
  try {
66036
- const voiceDir2 = join68(homedir17(), ".open-agents", "voice");
66315
+ const voiceDir2 = join69(homedir18(), ".open-agents", "voice");
66037
66316
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
66038
66317
  for (const pf of voicePidFiles) {
66039
- const pidPath = join68(voiceDir2, pf);
66040
- if (existsSync51(pidPath)) {
66318
+ const pidPath = join69(voiceDir2, pf);
66319
+ if (existsSync52(pidPath)) {
66041
66320
  try {
66042
- const pid = parseInt(readFileSync40(pidPath, "utf8").trim(), 10);
66321
+ const pid = parseInt(readFileSync41(pidPath, "utf8").trim(), 10);
66043
66322
  if (pid > 0) {
66044
66323
  if (process.platform === "win32") {
66045
66324
  try {
@@ -66063,8 +66342,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
66063
66342
  execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
66064
66343
  } catch {
66065
66344
  }
66066
- const oaPath = join68(repoRoot, OA_DIR);
66067
- if (existsSync51(oaPath)) {
66345
+ const oaPath = join69(repoRoot, OA_DIR);
66346
+ if (existsSync52(oaPath)) {
66068
66347
  let deleted = false;
66069
66348
  for (let attempt = 0; attempt < 3; attempt++) {
66070
66349
  try {
@@ -66445,8 +66724,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
66445
66724
  }
66446
66725
  }
66447
66726
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
66448
- const isImage = isImagePath(cleanPath) && existsSync51(resolve32(repoRoot, cleanPath));
66449
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync51(resolve32(repoRoot, cleanPath));
66727
+ const isImage = isImagePath(cleanPath) && existsSync52(resolve32(repoRoot, cleanPath));
66728
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync52(resolve32(repoRoot, cleanPath));
66450
66729
  if (activeTask) {
66451
66730
  if (activeTask.runner.isPaused) {
66452
66731
  activeTask.runner.resume();
@@ -66455,7 +66734,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
66455
66734
  if (isImage) {
66456
66735
  try {
66457
66736
  const imgPath = resolve32(repoRoot, cleanPath);
66458
- const imgBuffer = readFileSync40(imgPath);
66737
+ const imgBuffer = readFileSync41(imgPath);
66459
66738
  const base64 = imgBuffer.toString("base64");
66460
66739
  const ext = extname11(cleanPath).toLowerCase();
66461
66740
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -66692,13 +66971,13 @@ NEW TASK: ${fullInput}`;
66692
66971
  writeContent(() => renderError(errMsg));
66693
66972
  if (failureStore) {
66694
66973
  try {
66695
- const { createHash: createHash6 } = await import("node:crypto");
66974
+ const { createHash: createHash7 } = await import("node:crypto");
66696
66975
  failureStore.insert({
66697
66976
  taskId: "",
66698
66977
  sessionId: `${Date.now()}`,
66699
66978
  repoRoot,
66700
66979
  failureType: "runtime-error",
66701
- fingerprint: createHash6("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
66980
+ fingerprint: createHash7("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
66702
66981
  filePath: null,
66703
66982
  errorMessage: errMsg.slice(0, 500),
66704
66983
  context: null,
@@ -66954,13 +67233,13 @@ async function runWithTUI(task, config, repoPath) {
66954
67233
  const handle = startTask(task, config, repoRoot);
66955
67234
  await handle.promise;
66956
67235
  try {
66957
- const ikDir = join68(repoRoot, ".oa", "identity");
66958
- const ikFile = join68(ikDir, "self-state.json");
67236
+ const ikDir = join69(repoRoot, ".oa", "identity");
67237
+ const ikFile = join69(ikDir, "self-state.json");
66959
67238
  let ikState;
66960
- if (existsSync51(ikFile)) {
66961
- ikState = JSON.parse(readFileSync40(ikFile, "utf8"));
67239
+ if (existsSync52(ikFile)) {
67240
+ ikState = JSON.parse(readFileSync41(ikFile, "utf8"));
66962
67241
  } else {
66963
- mkdirSync25(ikDir, { recursive: true });
67242
+ mkdirSync26(ikDir, { recursive: true });
66964
67243
  ikState = {
66965
67244
  self_id: `oa-${Date.now().toString(36)}`,
66966
67245
  version: 1,
@@ -66982,7 +67261,7 @@ async function runWithTUI(task, config, repoPath) {
66982
67261
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
66983
67262
  ikState.session_count = (ikState.session_count || 0) + 1;
66984
67263
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
66985
- writeFileSync24(ikFile, JSON.stringify(ikState, null, 2));
67264
+ writeFileSync25(ikFile, JSON.stringify(ikState, null, 2));
66986
67265
  } catch (ikErr) {
66987
67266
  }
66988
67267
  try {
@@ -66991,12 +67270,12 @@ async function runWithTUI(task, config, repoPath) {
66991
67270
  ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
66992
67271
  } catch {
66993
67272
  try {
66994
- const archeDir = join68(repoRoot, ".oa", "arche");
66995
- const archeFile = join68(archeDir, "variants.json");
67273
+ const archeDir = join69(repoRoot, ".oa", "arche");
67274
+ const archeFile = join69(archeDir, "variants.json");
66996
67275
  let variants = [];
66997
67276
  try {
66998
- if (existsSync51(archeFile))
66999
- variants = JSON.parse(readFileSync40(archeFile, "utf8"));
67277
+ if (existsSync52(archeFile))
67278
+ variants = JSON.parse(readFileSync41(archeFile, "utf8"));
67000
67279
  } catch {
67001
67280
  }
67002
67281
  variants.push({
@@ -67011,15 +67290,15 @@ async function runWithTUI(task, config, repoPath) {
67011
67290
  });
67012
67291
  if (variants.length > 50)
67013
67292
  variants = variants.slice(-50);
67014
- mkdirSync25(archeDir, { recursive: true });
67015
- writeFileSync24(archeFile, JSON.stringify(variants, null, 2));
67293
+ mkdirSync26(archeDir, { recursive: true });
67294
+ writeFileSync25(archeFile, JSON.stringify(variants, null, 2));
67016
67295
  } catch {
67017
67296
  }
67018
67297
  }
67019
67298
  try {
67020
- const metaFile = join68(repoRoot, ".oa", "memory", "metabolism", "store.json");
67021
- if (existsSync51(metaFile)) {
67022
- const store = JSON.parse(readFileSync40(metaFile, "utf8"));
67299
+ const metaFile = join69(repoRoot, ".oa", "memory", "metabolism", "store.json");
67300
+ if (existsSync52(metaFile)) {
67301
+ const store = JSON.parse(readFileSync41(metaFile, "utf8"));
67023
67302
  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);
67024
67303
  let updated = false;
67025
67304
  for (const item of surfaced) {
@@ -67030,7 +67309,7 @@ async function runWithTUI(task, config, repoPath) {
67030
67309
  updated = true;
67031
67310
  }
67032
67311
  if (updated) {
67033
- writeFileSync24(metaFile, JSON.stringify(store, null, 2));
67312
+ writeFileSync25(metaFile, JSON.stringify(store, null, 2));
67034
67313
  }
67035
67314
  }
67036
67315
  } catch {
@@ -67083,9 +67362,9 @@ Rules:
67083
67362
  try {
67084
67363
  const { initDb: initDb2 } = __require("@open-agents/memory");
67085
67364
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
67086
- const dbDir = join68(repoRoot, ".oa", "memory");
67087
- mkdirSync25(dbDir, { recursive: true });
67088
- const db = initDb2(join68(dbDir, "structured.db"));
67365
+ const dbDir = join69(repoRoot, ".oa", "memory");
67366
+ mkdirSync26(dbDir, { recursive: true });
67367
+ const db = initDb2(join69(dbDir, "structured.db"));
67089
67368
  const memStore = new ProceduralMemoryStore2(db);
67090
67369
  memStore.createWithEmbedding({
67091
67370
  content: content.slice(0, 600),
@@ -67100,12 +67379,12 @@ Rules:
67100
67379
  db.close();
67101
67380
  } catch {
67102
67381
  }
67103
- const metaDir = join68(repoRoot, ".oa", "memory", "metabolism");
67104
- const storeFile = join68(metaDir, "store.json");
67382
+ const metaDir = join69(repoRoot, ".oa", "memory", "metabolism");
67383
+ const storeFile = join69(metaDir, "store.json");
67105
67384
  let store = [];
67106
67385
  try {
67107
- if (existsSync51(storeFile))
67108
- store = JSON.parse(readFileSync40(storeFile, "utf8"));
67386
+ if (existsSync52(storeFile))
67387
+ store = JSON.parse(readFileSync41(storeFile, "utf8"));
67109
67388
  } catch {
67110
67389
  }
67111
67390
  store.push({
@@ -67121,26 +67400,26 @@ Rules:
67121
67400
  });
67122
67401
  if (store.length > 100)
67123
67402
  store = store.slice(-100);
67124
- mkdirSync25(metaDir, { recursive: true });
67125
- writeFileSync24(storeFile, JSON.stringify(store, null, 2));
67403
+ mkdirSync26(metaDir, { recursive: true });
67404
+ writeFileSync25(storeFile, JSON.stringify(store, null, 2));
67126
67405
  }
67127
67406
  }
67128
67407
  } catch {
67129
67408
  }
67130
67409
  try {
67131
- const cohereSettingsFile = join68(repoRoot, ".oa", "settings.json");
67410
+ const cohereSettingsFile = join69(repoRoot, ".oa", "settings.json");
67132
67411
  let cohereActive = false;
67133
67412
  try {
67134
- if (existsSync51(cohereSettingsFile)) {
67135
- const settings = JSON.parse(readFileSync40(cohereSettingsFile, "utf8"));
67413
+ if (existsSync52(cohereSettingsFile)) {
67414
+ const settings = JSON.parse(readFileSync41(cohereSettingsFile, "utf8"));
67136
67415
  cohereActive = settings.cohere === true;
67137
67416
  }
67138
67417
  } catch {
67139
67418
  }
67140
67419
  if (cohereActive) {
67141
- const metaFile = join68(repoRoot, ".oa", "memory", "metabolism", "store.json");
67142
- if (existsSync51(metaFile)) {
67143
- const store = JSON.parse(readFileSync40(metaFile, "utf8"));
67420
+ const metaFile = join69(repoRoot, ".oa", "memory", "metabolism", "store.json");
67421
+ if (existsSync52(metaFile)) {
67422
+ const store = JSON.parse(readFileSync41(metaFile, "utf8"));
67144
67423
  const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
67145
67424
  if (latest && latest.scores?.confidence >= 0.6) {
67146
67425
  try {
@@ -67165,18 +67444,18 @@ Rules:
67165
67444
  }
67166
67445
  } catch (err) {
67167
67446
  try {
67168
- const ikFile = join68(repoRoot, ".oa", "identity", "self-state.json");
67169
- if (existsSync51(ikFile)) {
67170
- const ikState = JSON.parse(readFileSync40(ikFile, "utf8"));
67447
+ const ikFile = join69(repoRoot, ".oa", "identity", "self-state.json");
67448
+ if (existsSync52(ikFile)) {
67449
+ const ikState = JSON.parse(readFileSync41(ikFile, "utf8"));
67171
67450
  ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
67172
67451
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
67173
67452
  ikState.session_count = (ikState.session_count || 0) + 1;
67174
67453
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
67175
- writeFileSync24(ikFile, JSON.stringify(ikState, null, 2));
67454
+ writeFileSync25(ikFile, JSON.stringify(ikState, null, 2));
67176
67455
  }
67177
- const metaFile = join68(repoRoot, ".oa", "memory", "metabolism", "store.json");
67178
- if (existsSync51(metaFile)) {
67179
- const store = JSON.parse(readFileSync40(metaFile, "utf8"));
67456
+ const metaFile = join69(repoRoot, ".oa", "memory", "metabolism", "store.json");
67457
+ if (existsSync52(metaFile)) {
67458
+ const store = JSON.parse(readFileSync41(metaFile, "utf8"));
67180
67459
  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);
67181
67460
  for (const item of surfaced) {
67182
67461
  item.accessCount = (item.accessCount || 0) + 1;
@@ -67184,15 +67463,15 @@ Rules:
67184
67463
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
67185
67464
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
67186
67465
  }
67187
- writeFileSync24(metaFile, JSON.stringify(store, null, 2));
67466
+ writeFileSync25(metaFile, JSON.stringify(store, null, 2));
67188
67467
  }
67189
67468
  try {
67190
- const archeDir = join68(repoRoot, ".oa", "arche");
67191
- const archeFile = join68(archeDir, "variants.json");
67469
+ const archeDir = join69(repoRoot, ".oa", "arche");
67470
+ const archeFile = join69(archeDir, "variants.json");
67192
67471
  let variants = [];
67193
67472
  try {
67194
- if (existsSync51(archeFile))
67195
- variants = JSON.parse(readFileSync40(archeFile, "utf8"));
67473
+ if (existsSync52(archeFile))
67474
+ variants = JSON.parse(readFileSync41(archeFile, "utf8"));
67196
67475
  } catch {
67197
67476
  }
67198
67477
  variants.push({
@@ -67207,8 +67486,8 @@ Rules:
67207
67486
  });
67208
67487
  if (variants.length > 50)
67209
67488
  variants = variants.slice(-50);
67210
- mkdirSync25(archeDir, { recursive: true });
67211
- writeFileSync24(archeFile, JSON.stringify(variants, null, 2));
67489
+ mkdirSync26(archeDir, { recursive: true });
67490
+ writeFileSync25(archeFile, JSON.stringify(variants, null, 2));
67212
67491
  } catch {
67213
67492
  }
67214
67493
  } catch {
@@ -67275,13 +67554,13 @@ __export(run_exports, {
67275
67554
  });
67276
67555
  import { resolve as resolve33 } from "node:path";
67277
67556
  import { spawn as spawn21 } from "node:child_process";
67278
- import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync25, readFileSync as readFileSync41, readdirSync as readdirSync21, existsSync as existsSync52 } from "node:fs";
67279
- import { randomBytes as randomBytes16 } from "node:crypto";
67280
- import { join as join69 } from "node:path";
67557
+ import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26, readFileSync as readFileSync42, readdirSync as readdirSync22, existsSync as existsSync53 } from "node:fs";
67558
+ import { randomBytes as randomBytes17 } from "node:crypto";
67559
+ import { join as join70 } from "node:path";
67281
67560
  function jobsDir2(repoPath) {
67282
67561
  const root = resolve33(repoPath ?? process.cwd());
67283
- const dir = join69(root, ".oa", "jobs");
67284
- mkdirSync26(dir, { recursive: true });
67562
+ const dir = join70(root, ".oa", "jobs");
67563
+ mkdirSync27(dir, { recursive: true });
67285
67564
  return dir;
67286
67565
  }
67287
67566
  async function runCommand(opts, config) {
@@ -67344,7 +67623,7 @@ function extractSummary(captured) {
67344
67623
  return lines.slice(-3).join(" ").slice(0, 200);
67345
67624
  }
67346
67625
  async function runBackground(task, config, opts) {
67347
- const id = `job-${randomBytes16(3).toString("hex")}`;
67626
+ const id = `job-${randomBytes17(3).toString("hex")}`;
67348
67627
  const dir = jobsDir2(opts.repoPath);
67349
67628
  const repoRoot = resolve33(opts.repoPath ?? process.cwd());
67350
67629
  const job = {
@@ -67366,7 +67645,7 @@ async function runBackground(task, config, opts) {
67366
67645
  });
67367
67646
  child.unref();
67368
67647
  job.pid = child.pid ?? 0;
67369
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
67648
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
67370
67649
  let output = "";
67371
67650
  child.stdout?.on("data", (chunk) => {
67372
67651
  output += chunk.toString();
@@ -67382,7 +67661,7 @@ async function runBackground(task, config, opts) {
67382
67661
  job.summary = result.summary;
67383
67662
  job.durationMs = result.durationMs;
67384
67663
  job.error = result.error;
67385
- writeFileSync25(join69(dir, `${id}.json`), JSON.stringify(job, null, 2));
67664
+ writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
67386
67665
  } catch {
67387
67666
  }
67388
67667
  });
@@ -67398,13 +67677,13 @@ async function runBackground(task, config, opts) {
67398
67677
  }
67399
67678
  function statusCommand(jobId, repoPath) {
67400
67679
  const dir = jobsDir2(repoPath);
67401
- const file = join69(dir, `${jobId}.json`);
67402
- if (!existsSync52(file)) {
67680
+ const file = join70(dir, `${jobId}.json`);
67681
+ if (!existsSync53(file)) {
67403
67682
  console.error(`Job not found: ${jobId}`);
67404
67683
  console.log(`Available jobs: oa jobs`);
67405
67684
  process.exit(1);
67406
67685
  }
67407
- const job = JSON.parse(readFileSync41(file, "utf-8"));
67686
+ const job = JSON.parse(readFileSync42(file, "utf-8"));
67408
67687
  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`;
67409
67688
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
67410
67689
  console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
@@ -67419,7 +67698,7 @@ function statusCommand(jobId, repoPath) {
67419
67698
  }
67420
67699
  function jobsCommand(repoPath) {
67421
67700
  const dir = jobsDir2(repoPath);
67422
- const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).sort();
67701
+ const files = readdirSync22(dir).filter((f) => f.endsWith(".json")).sort();
67423
67702
  if (files.length === 0) {
67424
67703
  console.log("No jobs found.");
67425
67704
  return;
@@ -67427,7 +67706,7 @@ function jobsCommand(repoPath) {
67427
67706
  console.log("Jobs:");
67428
67707
  for (const file of files) {
67429
67708
  try {
67430
- const job = JSON.parse(readFileSync41(join69(dir, file), "utf-8"));
67709
+ const job = JSON.parse(readFileSync42(join70(dir, file), "utf-8"));
67431
67710
  const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
67432
67711
  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`;
67433
67712
  console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
@@ -67446,8 +67725,8 @@ var init_run = __esm({
67446
67725
  import { glob } from "glob";
67447
67726
  import ignore from "ignore";
67448
67727
  import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
67449
- import { createHash as createHash5 } from "node:crypto";
67450
- import { join as join70, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
67728
+ import { createHash as createHash6 } from "node:crypto";
67729
+ import { join as join71, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
67451
67730
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
67452
67731
  var init_codebase_indexer = __esm({
67453
67732
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -67491,7 +67770,7 @@ var init_codebase_indexer = __esm({
67491
67770
  const ig = ignore.default();
67492
67771
  if (this.config.respectGitignore) {
67493
67772
  try {
67494
- const gitignoreContent = await readFile23(join70(this.config.rootDir, ".gitignore"), "utf-8");
67773
+ const gitignoreContent = await readFile23(join71(this.config.rootDir, ".gitignore"), "utf-8");
67495
67774
  ig.add(gitignoreContent);
67496
67775
  } catch {
67497
67776
  }
@@ -67506,13 +67785,13 @@ var init_codebase_indexer = __esm({
67506
67785
  for (const relativePath of files) {
67507
67786
  if (ig.ignores(relativePath))
67508
67787
  continue;
67509
- const fullPath = join70(this.config.rootDir, relativePath);
67788
+ const fullPath = join71(this.config.rootDir, relativePath);
67510
67789
  try {
67511
67790
  const fileStat = await stat4(fullPath);
67512
67791
  if (fileStat.size > this.config.maxFileSize)
67513
67792
  continue;
67514
67793
  const content = await readFile23(fullPath);
67515
- const hash = createHash5("sha256").update(content).digest("hex");
67794
+ const hash = createHash6("sha256").update(content).digest("hex");
67516
67795
  const ext = extname12(relativePath);
67517
67796
  indexed.push({
67518
67797
  path: fullPath,
@@ -67552,7 +67831,7 @@ var init_codebase_indexer = __esm({
67552
67831
  if (!child) {
67553
67832
  child = {
67554
67833
  name: part,
67555
- path: join70(current.path, part),
67834
+ path: join71(current.path, part),
67556
67835
  type: "directory",
67557
67836
  children: []
67558
67837
  };
@@ -67635,13 +67914,13 @@ __export(index_repo_exports, {
67635
67914
  indexRepoCommand: () => indexRepoCommand
67636
67915
  });
67637
67916
  import { resolve as resolve34 } from "node:path";
67638
- import { existsSync as existsSync53, statSync as statSync16 } from "node:fs";
67917
+ import { existsSync as existsSync54, statSync as statSync16 } from "node:fs";
67639
67918
  import { cwd as cwd2 } from "node:process";
67640
67919
  async function indexRepoCommand(opts, _config) {
67641
67920
  const repoRoot = resolve34(opts.repoPath ?? cwd2());
67642
67921
  printHeader("Index Repository");
67643
67922
  printInfo(`Indexing: ${repoRoot}`);
67644
- if (!existsSync53(repoRoot)) {
67923
+ if (!existsSync54(repoRoot)) {
67645
67924
  printError(`Path does not exist: ${repoRoot}`);
67646
67925
  process.exit(1);
67647
67926
  }
@@ -67893,8 +68172,8 @@ var config_exports = {};
67893
68172
  __export(config_exports, {
67894
68173
  configCommand: () => configCommand
67895
68174
  });
67896
- import { join as join71, resolve as resolve35 } from "node:path";
67897
- import { homedir as homedir18 } from "node:os";
68175
+ import { join as join72, resolve as resolve35 } from "node:path";
68176
+ import { homedir as homedir19 } from "node:os";
67898
68177
  import { cwd as cwd3 } from "node:process";
67899
68178
  function redactIfSensitive(key, value) {
67900
68179
  if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
@@ -67976,7 +68255,7 @@ function handleShow(opts, config) {
67976
68255
  }
67977
68256
  }
67978
68257
  printSection("Config File");
67979
- printInfo(`~/.open-agents/config.json (${join71(homedir18(), ".open-agents", "config.json")})`);
68258
+ printInfo(`~/.open-agents/config.json (${join72(homedir19(), ".open-agents", "config.json")})`);
67980
68259
  printSection("Priority Chain");
67981
68260
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
67982
68261
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -68015,7 +68294,7 @@ function handleSet(opts, _config) {
68015
68294
  const coerced = coerceForSettings(key, value);
68016
68295
  saveProjectSettings(repoRoot, { [key]: coerced });
68017
68296
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
68018
- printInfo(`Saved to ${join71(repoRoot, ".oa", "settings.json")}`);
68297
+ printInfo(`Saved to ${join72(repoRoot, ".oa", "settings.json")}`);
68019
68298
  printInfo("This override applies only when running in this workspace.");
68020
68299
  } catch (err) {
68021
68300
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -68158,8 +68437,8 @@ __export(eval_exports, {
68158
68437
  evalCommand: () => evalCommand
68159
68438
  });
68160
68439
  import { tmpdir as tmpdir10 } from "node:os";
68161
- import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26 } from "node:fs";
68162
- import { join as join72 } from "node:path";
68440
+ import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync27 } from "node:fs";
68441
+ import { join as join73 } from "node:path";
68163
68442
  async function evalCommand(opts, config) {
68164
68443
  const suiteName = opts.suite ?? "basic";
68165
68444
  const suite = SUITES[suiteName];
@@ -68284,9 +68563,9 @@ async function evalCommand(opts, config) {
68284
68563
  process.exit(failed > 0 ? 1 : 0);
68285
68564
  }
68286
68565
  function createTempEvalRepo() {
68287
- const dir = join72(tmpdir10(), `open-agents-eval-${Date.now()}`);
68288
- mkdirSync27(dir, { recursive: true });
68289
- writeFileSync26(join72(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
68566
+ const dir = join73(tmpdir10(), `open-agents-eval-${Date.now()}`);
68567
+ mkdirSync28(dir, { recursive: true });
68568
+ writeFileSync27(join73(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
68290
68569
  return dir;
68291
68570
  }
68292
68571
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -68346,7 +68625,7 @@ init_updater();
68346
68625
  import { parseArgs as nodeParseArgs2 } from "node:util";
68347
68626
  import { createRequire as createRequire4 } from "node:module";
68348
68627
  import { fileURLToPath as fileURLToPath14 } from "node:url";
68349
- import { dirname as dirname22, join as join73 } from "node:path";
68628
+ import { dirname as dirname22, join as join74 } from "node:path";
68350
68629
 
68351
68630
  // packages/cli/dist/cli.js
68352
68631
  import { createInterface } from "node:readline";
@@ -68453,7 +68732,7 @@ init_output();
68453
68732
  function getVersion5() {
68454
68733
  try {
68455
68734
  const require2 = createRequire4(import.meta.url);
68456
- const pkgPath = join73(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
68735
+ const pkgPath = join74(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
68457
68736
  const pkg = require2(pkgPath);
68458
68737
  return pkg.version;
68459
68738
  } catch {