open-agents-ai 0.103.11 → 0.103.13

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 +579 -357
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5422,8 +5422,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
5422
5422
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
5423
5423
  const filePath = join13(dir, `${name}.json`);
5424
5424
  if (existsSync10(filePath)) {
5425
- const { unlinkSync: unlinkSync7 } = __require("node:fs");
5426
- unlinkSync7(filePath);
5425
+ const { unlinkSync: unlinkSync8 } = __require("node:fs");
5426
+ unlinkSync8(filePath);
5427
5427
  return true;
5428
5428
  }
5429
5429
  return false;
@@ -16290,8 +16290,8 @@ var init_verifierRunner = __esm({
16290
16290
  if (patch.testsToRun.length === 0)
16291
16291
  return "(no tests specified)";
16292
16292
  const { execFile: execFile6 } = await import("node:child_process");
16293
- const { promisify: promisify5 } = await import("node:util");
16294
- const execFileAsync5 = promisify5(execFile6);
16293
+ const { promisify: promisify6 } = await import("node:util");
16294
+ const execFileAsync5 = promisify6(execFile6);
16295
16295
  const outputs = [];
16296
16296
  const workDir = this.options.workingDir || repoRoot;
16297
16297
  for (const cmd of patch.testsToRun.slice(0, 3)) {
@@ -18258,9 +18258,9 @@ ${marker}` : marker);
18258
18258
  if (!this._workingDirectory)
18259
18259
  return;
18260
18260
  try {
18261
- const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync17 } = __require("node:fs");
18262
- const { join: join54 } = __require("node:path");
18263
- const sessionDir = join54(this._workingDirectory, ".oa", "session", this._sessionId);
18261
+ const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync18 } = __require("node:fs");
18262
+ const { join: join55 } = __require("node:path");
18263
+ const sessionDir = join55(this._workingDirectory, ".oa", "session", this._sessionId);
18264
18264
  mkdirSync19(sessionDir, { recursive: true });
18265
18265
  const checkpoint = {
18266
18266
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -18273,7 +18273,7 @@ ${marker}` : marker);
18273
18273
  memexEntryCount: this._memexArchive.size,
18274
18274
  fileRegistrySize: this._fileRegistry.size
18275
18275
  };
18276
- writeFileSync17(join54(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
18276
+ writeFileSync18(join55(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
18277
18277
  } catch {
18278
18278
  }
18279
18279
  }
@@ -20362,9 +20362,9 @@ function ensureTranscribeCliBackground() {
20362
20362
  } catch {
20363
20363
  }
20364
20364
  try {
20365
- const { exec: exec2 } = await import("node:child_process");
20365
+ const { exec: exec3 } = await import("node:child_process");
20366
20366
  return new Promise((resolve31) => {
20367
- exec2("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
20367
+ exec3("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
20368
20368
  resolve31(!err);
20369
20369
  });
20370
20370
  });
@@ -25185,7 +25185,7 @@ function formatToolArgs(toolName, args, verbose) {
25185
25185
  case "memory_write":
25186
25186
  return `${args["topic"]}.${args["key"]}`;
25187
25187
  case "task_complete":
25188
- return truncStr(String(args["summary"] ?? ""), maxArg);
25188
+ return "";
25189
25189
  case "aiwg_setup":
25190
25190
  return String(args["framework"] ?? "sdlc");
25191
25191
  case "aiwg_health":
@@ -26203,6 +26203,8 @@ import { EventEmitter as EventEmitter3 } from "node:events";
26203
26203
  import { randomBytes as randomBytes7 } from "node:crypto";
26204
26204
  import { URL as URL2 } from "node:url";
26205
26205
  import { loadavg, cpus, totalmem, freemem } from "node:os";
26206
+ import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "node:fs";
26207
+ import { join as join35 } from "node:path";
26206
26208
  function cleanForwardHeaders(raw, targetHost) {
26207
26209
  const out = {};
26208
26210
  for (const [key, value] of Object.entries(raw)) {
@@ -26221,6 +26223,40 @@ function cleanForwardHeaders(raw, targetHost) {
26221
26223
  out.host = targetHost;
26222
26224
  return out;
26223
26225
  }
26226
+ function readExposeState(stateDir) {
26227
+ try {
26228
+ const path = join35(stateDir, STATE_FILE_NAME);
26229
+ if (!existsSync26(path))
26230
+ return null;
26231
+ const raw = readFileSync18(path, "utf8");
26232
+ const data = JSON.parse(raw);
26233
+ if (!data.pid || !data.tunnelUrl || !data.authKey || !data.proxyPort)
26234
+ return null;
26235
+ return data;
26236
+ } catch {
26237
+ return null;
26238
+ }
26239
+ }
26240
+ function writeExposeState(stateDir, state) {
26241
+ try {
26242
+ writeFileSync8(join35(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
26243
+ } catch {
26244
+ }
26245
+ }
26246
+ function removeExposeState(stateDir) {
26247
+ try {
26248
+ unlinkSync3(join35(stateDir, STATE_FILE_NAME));
26249
+ } catch {
26250
+ }
26251
+ }
26252
+ function isProcessAlive(pid) {
26253
+ try {
26254
+ process.kill(pid, 0);
26255
+ return true;
26256
+ } catch {
26257
+ return false;
26258
+ }
26259
+ }
26224
26260
  async function collectSystemMetricsAsync() {
26225
26261
  const [l1, l5, l15] = loadavg();
26226
26262
  const cores = cpus().length;
@@ -26269,7 +26305,7 @@ async function collectSystemMetricsAsync() {
26269
26305
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
26270
26306
  };
26271
26307
  }
26272
- var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, ExposeGateway;
26308
+ var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway;
26273
26309
  var init_expose = __esm({
26274
26310
  "packages/cli/dist/tui/expose.js"() {
26275
26311
  "use strict";
@@ -26291,14 +26327,18 @@ var init_expose = __esm({
26291
26327
  llvm: "http://127.0.0.1:8080",
26292
26328
  custom: "http://127.0.0.1:11434"
26293
26329
  };
26294
- ExposeGateway = class extends EventEmitter3 {
26330
+ STATE_FILE_NAME = "expose-state.json";
26331
+ ExposeGateway = class _ExposeGateway extends EventEmitter3 {
26295
26332
  options;
26296
26333
  server = null;
26297
26334
  cloudflaredProcess = null;
26335
+ /** PID of detached cloudflared (for killing on stop, even across OA restarts) */
26336
+ _cloudflaredPid = null;
26298
26337
  _tunnelUrl = null;
26299
26338
  _authKey;
26300
26339
  _targetUrl;
26301
26340
  _kind;
26341
+ _stateDir;
26302
26342
  _stats = {
26303
26343
  status: "standby",
26304
26344
  totalRequests: 0,
@@ -26326,6 +26366,7 @@ var init_expose = __esm({
26326
26366
  this.options = options;
26327
26367
  this._kind = options.kind;
26328
26368
  this._targetUrl = options.targetUrl ?? DEFAULT_TARGETS[options.kind];
26369
+ this._stateDir = options.stateDir ?? null;
26329
26370
  if (options.authKey === void 0 || options.authKey === "") {
26330
26371
  this._authKey = randomBytes7(24).toString("base64url");
26331
26372
  } else {
@@ -26345,24 +26386,101 @@ var init_expose = __esm({
26345
26386
  this._tunnelUrl = await this.startCloudflared(port);
26346
26387
  this._stats.status = "active";
26347
26388
  this.emitStats();
26389
+ if (this._stateDir) {
26390
+ writeExposeState(this._stateDir, {
26391
+ pid: this._cloudflaredPid,
26392
+ tunnelUrl: this._tunnelUrl,
26393
+ authKey: this._authKey,
26394
+ proxyPort: port,
26395
+ targetUrl: this._targetUrl,
26396
+ kind: this._kind,
26397
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
26398
+ });
26399
+ }
26400
+ return this._tunnelUrl;
26401
+ }
26402
+ /**
26403
+ * Reconnect to an existing detached cloudflared tunnel from a previous
26404
+ * OA session. Starts the proxy on the same port so cloudflared routes
26405
+ * traffic to it seamlessly.
26406
+ */
26407
+ async reconnect(state) {
26408
+ if (this.server)
26409
+ throw new Error("Gateway already running");
26410
+ if (!isProcessAlive(state.pid)) {
26411
+ if (this._stateDir)
26412
+ removeExposeState(this._stateDir);
26413
+ throw new Error("Cloudflared process is no longer running");
26414
+ }
26415
+ this._tunnelUrl = state.tunnelUrl;
26416
+ this._authKey = state.authKey;
26417
+ this._targetUrl = state.targetUrl;
26418
+ this._kind = state.kind;
26419
+ this._cloudflaredPid = state.pid;
26420
+ this._proxyPort = state.proxyPort;
26421
+ this.server = this.createProxyServer(state.proxyPort);
26422
+ await new Promise((resolve31, reject) => {
26423
+ this.server.listen(state.proxyPort, "127.0.0.1", () => resolve31());
26424
+ this.server.on("error", reject);
26425
+ });
26426
+ this._stats.status = "active";
26427
+ this.emitStats();
26348
26428
  return this._tunnelUrl;
26349
26429
  }
26350
26430
  async stop() {
26431
+ if (this._cloudflaredPid && isProcessAlive(this._cloudflaredPid)) {
26432
+ try {
26433
+ process.kill(this._cloudflaredPid, "SIGTERM");
26434
+ } catch {
26435
+ }
26436
+ }
26351
26437
  if (this.cloudflaredProcess) {
26352
- this.cloudflaredProcess.kill("SIGTERM");
26438
+ try {
26439
+ this.cloudflaredProcess.kill("SIGTERM");
26440
+ } catch {
26441
+ }
26353
26442
  this.cloudflaredProcess = null;
26354
26443
  }
26444
+ this._cloudflaredPid = null;
26355
26445
  if (this.server) {
26356
26446
  await new Promise((resolve31) => {
26357
26447
  this.server.close(() => resolve31());
26358
26448
  });
26359
26449
  this.server = null;
26360
26450
  }
26451
+ if (this._stateDir)
26452
+ removeExposeState(this._stateDir);
26361
26453
  this._tunnelUrl = null;
26362
26454
  this._stats.status = "standby";
26363
26455
  this._stats.activeConnections = 0;
26364
26456
  this.emitStats();
26365
26457
  }
26458
+ /**
26459
+ * Check for and reconnect to a surviving expose tunnel from a previous session.
26460
+ * Returns the gateway if reconnection succeeded, or null if no valid state found.
26461
+ */
26462
+ static async checkAndReconnect(stateDir, options) {
26463
+ const state = readExposeState(stateDir);
26464
+ if (!state)
26465
+ return null;
26466
+ if (!isProcessAlive(state.pid)) {
26467
+ removeExposeState(stateDir);
26468
+ return null;
26469
+ }
26470
+ const gateway = new _ExposeGateway({
26471
+ kind: state.kind,
26472
+ targetUrl: state.targetUrl,
26473
+ authKey: state.authKey,
26474
+ stateDir,
26475
+ ...options
26476
+ });
26477
+ try {
26478
+ await gateway.reconnect(state);
26479
+ return gateway;
26480
+ } catch {
26481
+ return null;
26482
+ }
26483
+ }
26366
26484
  // ── Proxy server ────────────────────────────────────────────────────────
26367
26485
  createProxyServer(localPort) {
26368
26486
  const target = new URL2(this._targetUrl);
@@ -26539,8 +26657,10 @@ var init_expose = __esm({
26539
26657
  "--proxy-keepalive-timeout",
26540
26658
  "300s"
26541
26659
  ], {
26660
+ detached: true,
26542
26661
  stdio: ["ignore", "pipe", "pipe"]
26543
26662
  });
26663
+ this._cloudflaredPid = this.cloudflaredProcess.pid ?? null;
26544
26664
  let urlFound = false;
26545
26665
  const handleOutput = (data) => {
26546
26666
  const text = data.toString();
@@ -26548,6 +26668,9 @@ var init_expose = __esm({
26548
26668
  if (urlMatch && !urlFound) {
26549
26669
  urlFound = true;
26550
26670
  clearTimeout(timeout);
26671
+ this.cloudflaredProcess?.unref();
26672
+ this.cloudflaredProcess?.stdout?.destroy();
26673
+ this.cloudflaredProcess?.stderr?.destroy();
26551
26674
  resolve31(urlMatch[0]);
26552
26675
  }
26553
26676
  };
@@ -26580,6 +26703,17 @@ var init_expose = __esm({
26580
26703
  this._stats.status = "active";
26581
26704
  this.emitStats();
26582
26705
  this.options.onInfo?.(`Tunnel restarted: ${this._tunnelUrl}`);
26706
+ if (this._stateDir) {
26707
+ writeExposeState(this._stateDir, {
26708
+ pid: this._cloudflaredPid,
26709
+ tunnelUrl: this._tunnelUrl,
26710
+ authKey: this._authKey,
26711
+ proxyPort: this._proxyPort,
26712
+ targetUrl: this._targetUrl,
26713
+ kind: this._kind,
26714
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
26715
+ });
26716
+ }
26583
26717
  } catch (err) {
26584
26718
  this.options.onError?.(`Tunnel restart failed: ${err instanceof Error ? err.message : String(err)}`);
26585
26719
  }
@@ -26652,8 +26786,8 @@ var init_types = __esm({
26652
26786
 
26653
26787
  // packages/cli/dist/tui/p2p/secret-vault.js
26654
26788
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
26655
- import { readFileSync as readFileSync18, writeFileSync as writeFileSync8, existsSync as existsSync26, mkdirSync as mkdirSync8 } from "node:fs";
26656
- import { join as join35, dirname as dirname13 } from "node:path";
26789
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync9, existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
26790
+ import { join as join36, dirname as dirname13 } from "node:path";
26657
26791
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
26658
26792
  var init_secret_vault = __esm({
26659
26793
  "packages/cli/dist/tui/p2p/secret-vault.js"() {
@@ -26865,18 +26999,18 @@ var init_secret_vault = __esm({
26865
26999
  const tag = cipher.getAuthTag();
26866
27000
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
26867
27001
  const dir = dirname13(this.storePath);
26868
- if (!existsSync26(dir))
27002
+ if (!existsSync27(dir))
26869
27003
  mkdirSync8(dir, { recursive: true });
26870
- writeFileSync8(this.storePath, blob, { mode: 384 });
27004
+ writeFileSync9(this.storePath, blob, { mode: 384 });
26871
27005
  }
26872
27006
  /**
26873
27007
  * Load vault from disk, decrypting with the given passphrase.
26874
27008
  * Returns the number of secrets loaded.
26875
27009
  */
26876
27010
  load(passphrase) {
26877
- if (!this.storePath || !existsSync26(this.storePath))
27011
+ if (!this.storePath || !existsSync27(this.storePath))
26878
27012
  return 0;
26879
- const blob = readFileSync18(this.storePath);
27013
+ const blob = readFileSync19(this.storePath);
26880
27014
  if (blob.length < SALT_LEN + IV_LEN + 16) {
26881
27015
  throw new Error("Vault file is corrupted (too small)");
26882
27016
  }
@@ -28096,17 +28230,17 @@ var init_render2 = __esm({
28096
28230
  });
28097
28231
 
28098
28232
  // packages/prompts/dist/promptLoader.js
28099
- import { readFileSync as readFileSync19, existsSync as existsSync27 } from "node:fs";
28100
- import { join as join36, dirname as dirname14 } from "node:path";
28233
+ import { readFileSync as readFileSync20, existsSync as existsSync28 } from "node:fs";
28234
+ import { join as join37, dirname as dirname14 } from "node:path";
28101
28235
  import { fileURLToPath as fileURLToPath9 } from "node:url";
28102
28236
  function loadPrompt2(promptPath, vars) {
28103
28237
  let content = cache2.get(promptPath);
28104
28238
  if (content === void 0) {
28105
- const fullPath = join36(PROMPTS_DIR2, promptPath);
28106
- if (!existsSync27(fullPath)) {
28239
+ const fullPath = join37(PROMPTS_DIR2, promptPath);
28240
+ if (!existsSync28(fullPath)) {
28107
28241
  throw new Error(`Prompt file not found: ${fullPath}`);
28108
28242
  }
28109
- content = readFileSync19(fullPath, "utf-8");
28243
+ content = readFileSync20(fullPath, "utf-8");
28110
28244
  cache2.set(promptPath, content);
28111
28245
  }
28112
28246
  if (!vars)
@@ -28119,9 +28253,9 @@ var init_promptLoader2 = __esm({
28119
28253
  "use strict";
28120
28254
  __filename2 = fileURLToPath9(import.meta.url);
28121
28255
  __dirname5 = dirname14(__filename2);
28122
- devPath = join36(__dirname5, "..", "templates");
28123
- publishedPath = join36(__dirname5, "..", "prompts", "templates");
28124
- PROMPTS_DIR2 = existsSync27(devPath) ? devPath : publishedPath;
28256
+ devPath = join37(__dirname5, "..", "templates");
28257
+ publishedPath = join37(__dirname5, "..", "prompts", "templates");
28258
+ PROMPTS_DIR2 = existsSync28(devPath) ? devPath : publishedPath;
28125
28259
  cache2 = /* @__PURE__ */ new Map();
28126
28260
  }
28127
28261
  });
@@ -28232,7 +28366,7 @@ var init_task_templates = __esm({
28232
28366
  });
28233
28367
 
28234
28368
  // packages/prompts/dist/index.js
28235
- import { join as join37, dirname as dirname15 } from "node:path";
28369
+ import { join as join38, dirname as dirname15 } from "node:path";
28236
28370
  import { fileURLToPath as fileURLToPath10 } from "node:url";
28237
28371
  var _dir, _packageRoot;
28238
28372
  var init_dist6 = __esm({
@@ -28243,26 +28377,26 @@ var init_dist6 = __esm({
28243
28377
  init_task_templates();
28244
28378
  init_render2();
28245
28379
  _dir = dirname15(fileURLToPath10(import.meta.url));
28246
- _packageRoot = join37(_dir, "..");
28380
+ _packageRoot = join38(_dir, "..");
28247
28381
  }
28248
28382
  });
28249
28383
 
28250
28384
  // packages/cli/dist/tui/oa-directory.js
28251
- import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync9, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
28252
- import { join as join38, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
28385
+ import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync4 } from "node:fs";
28386
+ import { join as join39, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
28253
28387
  import { homedir as homedir9 } from "node:os";
28254
28388
  function initOaDirectory(repoRoot) {
28255
- const oaPath = join38(repoRoot, OA_DIR);
28389
+ const oaPath = join39(repoRoot, OA_DIR);
28256
28390
  for (const sub of SUBDIRS) {
28257
- mkdirSync9(join38(oaPath, sub), { recursive: true });
28391
+ mkdirSync9(join39(oaPath, sub), { recursive: true });
28258
28392
  }
28259
28393
  try {
28260
- const gitignorePath = join38(repoRoot, ".gitignore");
28394
+ const gitignorePath = join39(repoRoot, ".gitignore");
28261
28395
  const settingsPattern = ".oa/settings.json";
28262
- if (existsSync28(gitignorePath)) {
28263
- const content = readFileSync20(gitignorePath, "utf-8");
28396
+ if (existsSync29(gitignorePath)) {
28397
+ const content = readFileSync21(gitignorePath, "utf-8");
28264
28398
  if (!content.includes(settingsPattern)) {
28265
- writeFileSync9(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
28399
+ writeFileSync10(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
28266
28400
  }
28267
28401
  }
28268
28402
  } catch {
@@ -28270,41 +28404,41 @@ function initOaDirectory(repoRoot) {
28270
28404
  return oaPath;
28271
28405
  }
28272
28406
  function hasOaDirectory(repoRoot) {
28273
- return existsSync28(join38(repoRoot, OA_DIR, "index"));
28407
+ return existsSync29(join39(repoRoot, OA_DIR, "index"));
28274
28408
  }
28275
28409
  function loadProjectSettings(repoRoot) {
28276
- const settingsPath = join38(repoRoot, OA_DIR, "settings.json");
28410
+ const settingsPath = join39(repoRoot, OA_DIR, "settings.json");
28277
28411
  try {
28278
- if (existsSync28(settingsPath)) {
28279
- return JSON.parse(readFileSync20(settingsPath, "utf-8"));
28412
+ if (existsSync29(settingsPath)) {
28413
+ return JSON.parse(readFileSync21(settingsPath, "utf-8"));
28280
28414
  }
28281
28415
  } catch {
28282
28416
  }
28283
28417
  return {};
28284
28418
  }
28285
28419
  function saveProjectSettings(repoRoot, settings) {
28286
- const oaPath = join38(repoRoot, OA_DIR);
28420
+ const oaPath = join39(repoRoot, OA_DIR);
28287
28421
  mkdirSync9(oaPath, { recursive: true });
28288
28422
  const existing = loadProjectSettings(repoRoot);
28289
28423
  const merged = { ...existing, ...settings };
28290
- writeFileSync9(join38(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28424
+ writeFileSync10(join39(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28291
28425
  }
28292
28426
  function loadGlobalSettings() {
28293
- const settingsPath = join38(homedir9(), ".open-agents", "settings.json");
28427
+ const settingsPath = join39(homedir9(), ".open-agents", "settings.json");
28294
28428
  try {
28295
- if (existsSync28(settingsPath)) {
28296
- return JSON.parse(readFileSync20(settingsPath, "utf-8"));
28429
+ if (existsSync29(settingsPath)) {
28430
+ return JSON.parse(readFileSync21(settingsPath, "utf-8"));
28297
28431
  }
28298
28432
  } catch {
28299
28433
  }
28300
28434
  return {};
28301
28435
  }
28302
28436
  function saveGlobalSettings(settings) {
28303
- const dir = join38(homedir9(), ".open-agents");
28437
+ const dir = join39(homedir9(), ".open-agents");
28304
28438
  mkdirSync9(dir, { recursive: true });
28305
28439
  const existing = loadGlobalSettings();
28306
28440
  const merged = { ...existing, ...settings };
28307
- writeFileSync9(join38(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28441
+ writeFileSync10(join39(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28308
28442
  }
28309
28443
  function resolveSettings(repoRoot) {
28310
28444
  const global = loadGlobalSettings();
@@ -28319,12 +28453,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
28319
28453
  while (dir && !visited.has(dir)) {
28320
28454
  visited.add(dir);
28321
28455
  for (const name of CONTEXT_FILES) {
28322
- const filePath = join38(dir, name);
28456
+ const filePath = join39(dir, name);
28323
28457
  const normalizedName = name.toLowerCase();
28324
- if (existsSync28(filePath) && !seen.has(filePath)) {
28458
+ if (existsSync29(filePath) && !seen.has(filePath)) {
28325
28459
  seen.add(filePath);
28326
28460
  try {
28327
- let content = readFileSync20(filePath, "utf-8");
28461
+ let content = readFileSync21(filePath, "utf-8");
28328
28462
  if (content.length > maxContentLen) {
28329
28463
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
28330
28464
  }
@@ -28338,11 +28472,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
28338
28472
  }
28339
28473
  }
28340
28474
  }
28341
- const projectMap = join38(dir, OA_DIR, "context", "project-map.md");
28342
- if (existsSync28(projectMap) && !seen.has(projectMap)) {
28475
+ const projectMap = join39(dir, OA_DIR, "context", "project-map.md");
28476
+ if (existsSync29(projectMap) && !seen.has(projectMap)) {
28343
28477
  seen.add(projectMap);
28344
28478
  try {
28345
- let content = readFileSync20(projectMap, "utf-8");
28479
+ let content = readFileSync21(projectMap, "utf-8");
28346
28480
  if (content.length > maxContentLen) {
28347
28481
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
28348
28482
  }
@@ -28354,7 +28488,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
28354
28488
  } catch {
28355
28489
  }
28356
28490
  }
28357
- const parent = join38(dir, "..");
28491
+ const parent = join39(dir, "..");
28358
28492
  if (parent === dir)
28359
28493
  break;
28360
28494
  dir = parent;
@@ -28372,9 +28506,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
28372
28506
  return found;
28373
28507
  }
28374
28508
  function readIndexMeta(repoRoot) {
28375
- const metaPath = join38(repoRoot, OA_DIR, "index", "meta.json");
28509
+ const metaPath = join39(repoRoot, OA_DIR, "index", "meta.json");
28376
28510
  try {
28377
- return JSON.parse(readFileSync20(metaPath, "utf-8"));
28511
+ return JSON.parse(readFileSync21(metaPath, "utf-8"));
28378
28512
  } catch {
28379
28513
  return null;
28380
28514
  }
@@ -28425,28 +28559,28 @@ ${tree}\`\`\`
28425
28559
  sections.push("");
28426
28560
  }
28427
28561
  const content = sections.join("\n");
28428
- const contextDir = join38(repoRoot, OA_DIR, "context");
28562
+ const contextDir = join39(repoRoot, OA_DIR, "context");
28429
28563
  mkdirSync9(contextDir, { recursive: true });
28430
- writeFileSync9(join38(contextDir, "project-map.md"), content, "utf-8");
28564
+ writeFileSync10(join39(contextDir, "project-map.md"), content, "utf-8");
28431
28565
  return content;
28432
28566
  }
28433
28567
  function saveSession(repoRoot, session) {
28434
- const historyDir = join38(repoRoot, OA_DIR, "history");
28568
+ const historyDir = join39(repoRoot, OA_DIR, "history");
28435
28569
  mkdirSync9(historyDir, { recursive: true });
28436
- writeFileSync9(join38(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
28570
+ writeFileSync10(join39(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
28437
28571
  }
28438
28572
  function loadRecentSessions(repoRoot, limit = 5) {
28439
- const historyDir = join38(repoRoot, OA_DIR, "history");
28440
- if (!existsSync28(historyDir))
28573
+ const historyDir = join39(repoRoot, OA_DIR, "history");
28574
+ if (!existsSync29(historyDir))
28441
28575
  return [];
28442
28576
  try {
28443
28577
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
28444
- const stat5 = statSync9(join38(historyDir, f));
28578
+ const stat5 = statSync9(join39(historyDir, f));
28445
28579
  return { file: f, mtime: stat5.mtimeMs };
28446
28580
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
28447
28581
  return files.map((f) => {
28448
28582
  try {
28449
- return JSON.parse(readFileSync20(join38(historyDir, f.file), "utf-8"));
28583
+ return JSON.parse(readFileSync21(join39(historyDir, f.file), "utf-8"));
28450
28584
  } catch {
28451
28585
  return null;
28452
28586
  }
@@ -28456,18 +28590,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
28456
28590
  }
28457
28591
  }
28458
28592
  function savePendingTask(repoRoot, task) {
28459
- const historyDir = join38(repoRoot, OA_DIR, "history");
28593
+ const historyDir = join39(repoRoot, OA_DIR, "history");
28460
28594
  mkdirSync9(historyDir, { recursive: true });
28461
- writeFileSync9(join38(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
28595
+ writeFileSync10(join39(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
28462
28596
  }
28463
28597
  function loadPendingTask(repoRoot) {
28464
- const filePath = join38(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
28598
+ const filePath = join39(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
28465
28599
  try {
28466
- if (!existsSync28(filePath))
28600
+ if (!existsSync29(filePath))
28467
28601
  return null;
28468
- const data = JSON.parse(readFileSync20(filePath, "utf-8"));
28602
+ const data = JSON.parse(readFileSync21(filePath, "utf-8"));
28469
28603
  try {
28470
- unlinkSync3(filePath);
28604
+ unlinkSync4(filePath);
28471
28605
  } catch {
28472
28606
  }
28473
28607
  return data;
@@ -28476,13 +28610,13 @@ function loadPendingTask(repoRoot) {
28476
28610
  }
28477
28611
  }
28478
28612
  function saveSessionContext(repoRoot, entry) {
28479
- const contextDir = join38(repoRoot, OA_DIR, "context");
28613
+ const contextDir = join39(repoRoot, OA_DIR, "context");
28480
28614
  mkdirSync9(contextDir, { recursive: true });
28481
- const filePath = join38(contextDir, CONTEXT_SAVE_FILE);
28615
+ const filePath = join39(contextDir, CONTEXT_SAVE_FILE);
28482
28616
  let ctx;
28483
28617
  try {
28484
- if (existsSync28(filePath)) {
28485
- ctx = JSON.parse(readFileSync20(filePath, "utf-8"));
28618
+ if (existsSync29(filePath)) {
28619
+ ctx = JSON.parse(readFileSync21(filePath, "utf-8"));
28486
28620
  } else {
28487
28621
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
28488
28622
  }
@@ -28494,14 +28628,14 @@ function saveSessionContext(repoRoot, entry) {
28494
28628
  ctx.entries = ctx.entries.slice(-ctx.maxEntries);
28495
28629
  }
28496
28630
  ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
28497
- writeFileSync9(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
28631
+ writeFileSync10(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
28498
28632
  }
28499
28633
  function loadSessionContext(repoRoot) {
28500
- const filePath = join38(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
28634
+ const filePath = join39(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
28501
28635
  try {
28502
- if (!existsSync28(filePath))
28636
+ if (!existsSync29(filePath))
28503
28637
  return null;
28504
- return JSON.parse(readFileSync20(filePath, "utf-8"));
28638
+ return JSON.parse(readFileSync21(filePath, "utf-8"));
28505
28639
  } catch {
28506
28640
  return null;
28507
28641
  }
@@ -28548,12 +28682,12 @@ function detectManifests(repoRoot) {
28548
28682
  { file: "docker-compose.yaml", type: "Docker Compose" }
28549
28683
  ];
28550
28684
  for (const check of checks) {
28551
- const filePath = join38(repoRoot, check.file);
28552
- if (existsSync28(filePath)) {
28685
+ const filePath = join39(repoRoot, check.file);
28686
+ if (existsSync29(filePath)) {
28553
28687
  let name;
28554
28688
  if (check.nameField) {
28555
28689
  try {
28556
- const data = JSON.parse(readFileSync20(filePath, "utf-8"));
28690
+ const data = JSON.parse(readFileSync21(filePath, "utf-8"));
28557
28691
  name = data[check.nameField];
28558
28692
  } catch {
28559
28693
  }
@@ -28582,7 +28716,7 @@ function findKeyFiles(repoRoot) {
28582
28716
  { pattern: "CLAUDE.md", description: "Claude Code context" }
28583
28717
  ];
28584
28718
  for (const check of checks) {
28585
- if (existsSync28(join38(repoRoot, check.pattern))) {
28719
+ if (existsSync29(join39(repoRoot, check.pattern))) {
28586
28720
  keyFiles.push({ path: check.pattern, description: check.description });
28587
28721
  }
28588
28722
  }
@@ -28608,12 +28742,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
28608
28742
  if (entry.isDirectory()) {
28609
28743
  let fileCount = 0;
28610
28744
  try {
28611
- fileCount = readdirSync7(join38(root, entry.name)).filter((f) => !f.startsWith(".")).length;
28745
+ fileCount = readdirSync7(join39(root, entry.name)).filter((f) => !f.startsWith(".")).length;
28612
28746
  } catch {
28613
28747
  }
28614
28748
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
28615
28749
  `;
28616
- result += buildDirTree(join38(root, entry.name), maxDepth, childPrefix, depth + 1);
28750
+ result += buildDirTree(join39(root, entry.name), maxDepth, childPrefix, depth + 1);
28617
28751
  } else if (depth < maxDepth) {
28618
28752
  result += `${prefix}${connector}${entry.name}
28619
28753
  `;
@@ -28625,17 +28759,17 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
28625
28759
  }
28626
28760
  function loadUsageFile(filePath) {
28627
28761
  try {
28628
- if (existsSync28(filePath)) {
28629
- return JSON.parse(readFileSync20(filePath, "utf-8"));
28762
+ if (existsSync29(filePath)) {
28763
+ return JSON.parse(readFileSync21(filePath, "utf-8"));
28630
28764
  }
28631
28765
  } catch {
28632
28766
  }
28633
28767
  return { records: [] };
28634
28768
  }
28635
28769
  function saveUsageFile(filePath, data) {
28636
- const dir = join38(filePath, "..");
28770
+ const dir = join39(filePath, "..");
28637
28771
  mkdirSync9(dir, { recursive: true });
28638
- writeFileSync9(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28772
+ writeFileSync10(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28639
28773
  }
28640
28774
  function recordUsage(kind, value, opts) {
28641
28775
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -28663,15 +28797,15 @@ function recordUsage(kind, value, opts) {
28663
28797
  }
28664
28798
  saveUsageFile(filePath, data);
28665
28799
  };
28666
- update(join38(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
28800
+ update(join39(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
28667
28801
  if (opts?.repoRoot) {
28668
- update(join38(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
28802
+ update(join39(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
28669
28803
  }
28670
28804
  }
28671
28805
  function loadUsageHistory(kind, repoRoot) {
28672
- const globalPath = join38(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
28806
+ const globalPath = join39(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
28673
28807
  const globalData = loadUsageFile(globalPath);
28674
- const localData = repoRoot ? loadUsageFile(join38(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
28808
+ const localData = repoRoot ? loadUsageFile(join39(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
28675
28809
  const map = /* @__PURE__ */ new Map();
28676
28810
  for (const r of globalData.records) {
28677
28811
  if (r.kind !== kind)
@@ -28738,9 +28872,10 @@ var init_oa_directory = __esm({
28738
28872
 
28739
28873
  // packages/cli/dist/tui/setup.js
28740
28874
  import * as readline from "node:readline";
28741
- import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
28742
- import { existsSync as existsSync29, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
28743
- import { join as join39 } from "node:path";
28875
+ import { execSync as execSync25, spawn as spawn15, exec as exec2 } from "node:child_process";
28876
+ import { promisify as promisify5 } from "node:util";
28877
+ import { existsSync as existsSync30, writeFileSync as writeFileSync11, mkdirSync as mkdirSync10 } from "node:fs";
28878
+ import { join as join40 } from "node:path";
28744
28879
  import { homedir as homedir10, platform } from "node:os";
28745
28880
  function detectSystemSpecs() {
28746
28881
  let totalRamGB = 0;
@@ -28789,6 +28924,50 @@ function detectSystemSpecs() {
28789
28924
  gpuName
28790
28925
  };
28791
28926
  }
28927
+ async function detectSystemSpecsAsync() {
28928
+ let totalRamGB = 0;
28929
+ let availableRamGB = 0;
28930
+ let gpuVramGB = 0;
28931
+ let gpuName = "";
28932
+ try {
28933
+ const { stdout: memInfo } = await execAsync("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", { timeout: 5e3 });
28934
+ if (memInfo.includes("Mem:")) {
28935
+ const match = memInfo.match(/^Mem:\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/m);
28936
+ if (match) {
28937
+ totalRamGB = parseInt(match[1], 10) / 1024 ** 3;
28938
+ availableRamGB = parseInt(match[2], 10) / 1024 ** 3;
28939
+ }
28940
+ } else {
28941
+ const bytes = parseInt(memInfo.trim(), 10);
28942
+ if (!isNaN(bytes)) {
28943
+ totalRamGB = bytes / 1024 ** 3;
28944
+ availableRamGB = totalRamGB * 0.7;
28945
+ }
28946
+ }
28947
+ } catch {
28948
+ }
28949
+ try {
28950
+ const { stdout: nvidiaSmi } = await execAsync("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { timeout: 5e3 });
28951
+ const lines = nvidiaSmi.trim().split("\n");
28952
+ if (lines.length > 0) {
28953
+ for (const line of lines) {
28954
+ const parts = line.split(",").map((s) => s.trim());
28955
+ const vramMB = parseInt(parts[0] ?? "0", 10);
28956
+ if (!isNaN(vramMB))
28957
+ gpuVramGB += vramMB / 1024;
28958
+ if (!gpuName && parts[1])
28959
+ gpuName = parts[1];
28960
+ }
28961
+ }
28962
+ } catch {
28963
+ }
28964
+ return {
28965
+ totalRamGB: Math.round(totalRamGB * 10) / 10,
28966
+ availableRamGB: Math.round(availableRamGB * 10) / 10,
28967
+ gpuVramGB: Math.round(gpuVramGB * 10) / 10,
28968
+ gpuName
28969
+ };
28970
+ }
28792
28971
  function recommendModel(specs) {
28793
28972
  const effectiveGB = Math.max(specs.gpuVramGB, specs.availableRamGB);
28794
28973
  const budget = effectiveGB * 0.8;
@@ -28973,7 +29152,7 @@ async function installOllamaMac(_rl) {
28973
29152
  execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
28974
29153
  if (!hasCmd("brew")) {
28975
29154
  try {
28976
- const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
29155
+ const brewPrefix = existsSync30("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
28977
29156
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
28978
29157
  } catch {
28979
29158
  }
@@ -29727,10 +29906,10 @@ async function doSetup(config, rl) {
29727
29906
  `PARAMETER num_predict ${numPredict}`,
29728
29907
  `PARAMETER stop "<|endoftext|>"`
29729
29908
  ].join("\n");
29730
- const modelDir2 = join39(homedir10(), ".open-agents", "models");
29909
+ const modelDir2 = join40(homedir10(), ".open-agents", "models");
29731
29910
  mkdirSync10(modelDir2, { recursive: true });
29732
- const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
29733
- writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
29911
+ const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
29912
+ writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
29734
29913
  process.stdout.write(` ${c2.dim("Creating model...")} `);
29735
29914
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
29736
29915
  stdio: "pipe",
@@ -29775,7 +29954,7 @@ async function isModelAvailable(config) {
29775
29954
  }
29776
29955
  function isFirstRun() {
29777
29956
  try {
29778
- return !existsSync29(join39(homedir10(), ".open-agents", "config.json"));
29957
+ return !existsSync30(join40(homedir10(), ".open-agents", "config.json"));
29779
29958
  } catch {
29780
29959
  return true;
29781
29960
  }
@@ -29812,7 +29991,7 @@ function detectPkgManager() {
29812
29991
  return null;
29813
29992
  }
29814
29993
  function getVenvDir() {
29815
- return join39(homedir10(), ".open-agents", "venv");
29994
+ return join40(homedir10(), ".open-agents", "venv");
29816
29995
  }
29817
29996
  function hasVenvModule() {
29818
29997
  try {
@@ -29824,8 +30003,8 @@ function hasVenvModule() {
29824
30003
  }
29825
30004
  function ensureVenv(log) {
29826
30005
  const venvDir = getVenvDir();
29827
- const venvPip = join39(venvDir, "bin", "pip");
29828
- if (existsSync29(venvPip))
30006
+ const venvPip = join40(venvDir, "bin", "pip");
30007
+ if (existsSync30(venvPip))
29829
30008
  return venvDir;
29830
30009
  log("Creating Python venv for vision deps...");
29831
30010
  if (!hasCmd("python3")) {
@@ -29837,9 +30016,9 @@ function ensureVenv(log) {
29837
30016
  return null;
29838
30017
  }
29839
30018
  try {
29840
- mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
30019
+ mkdirSync10(join40(homedir10(), ".open-agents"), { recursive: true });
29841
30020
  execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
29842
- execSync25(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
30021
+ execSync25(`"${join40(venvDir, "bin", "pip")}" install --upgrade pip`, {
29843
30022
  stdio: "pipe",
29844
30023
  timeout: 6e4
29845
30024
  });
@@ -30030,15 +30209,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
30030
30209
  }
30031
30210
  }
30032
30211
  const venvDir = getVenvDir();
30033
- const venvBin = join39(venvDir, "bin");
30034
- const venvMoondream = join39(venvBin, "moondream-station");
30212
+ const venvBin = join40(venvDir, "bin");
30213
+ const venvMoondream = join40(venvBin, "moondream-station");
30035
30214
  const venv = ensureVenv(log);
30036
- if (venv && !hasCmd("moondream-station") && !existsSync29(venvMoondream)) {
30037
- const venvPip = join39(venvBin, "pip");
30215
+ if (venv && !hasCmd("moondream-station") && !existsSync30(venvMoondream)) {
30216
+ const venvPip = join40(venvBin, "pip");
30038
30217
  log("Installing moondream-station in ~/.open-agents/venv...");
30039
30218
  try {
30040
30219
  execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
30041
- if (existsSync29(venvMoondream)) {
30220
+ if (existsSync30(venvMoondream)) {
30042
30221
  log("moondream-station installed successfully.");
30043
30222
  } else {
30044
30223
  try {
@@ -30055,8 +30234,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
30055
30234
  }
30056
30235
  }
30057
30236
  if (venv) {
30058
- const venvPython = join39(venvBin, "python");
30059
- const venvPip2 = join39(venvBin, "pip");
30237
+ const venvPython = join40(venvBin, "python");
30238
+ const venvPip2 = join40(venvBin, "pip");
30060
30239
  let ocrStackInstalled = false;
30061
30240
  try {
30062
30241
  execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
@@ -30157,7 +30336,7 @@ function modelSizeGB(models, modelName) {
30157
30336
  const known = QWEN_VARIANTS.find((v) => modelName.includes(v.tag.split(":")[1] ?? ""));
30158
30337
  return known?.sizeGB ?? 4;
30159
30338
  }
30160
- function createExpandedVariant(baseModel, specs, sizeGB) {
30339
+ async function createExpandedVariantAsync(baseModel, specs, sizeGB) {
30161
30340
  const customName = expandedModelName(baseModel);
30162
30341
  const ctx = calculateContextWindow(specs, sizeGB);
30163
30342
  try {
@@ -30169,12 +30348,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
30169
30348
  `PARAMETER num_predict ${numPredict}`,
30170
30349
  `PARAMETER stop "<|endoftext|>"`
30171
30350
  ].join("\n");
30172
- const modelDir2 = join39(homedir10(), ".open-agents", "models");
30351
+ const modelDir2 = join40(homedir10(), ".open-agents", "models");
30173
30352
  mkdirSync10(modelDir2, { recursive: true });
30174
- const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
30175
- writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
30176
- execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
30177
- stdio: "pipe",
30353
+ const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
30354
+ writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
30355
+ await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
30178
30356
  timeout: 12e4
30179
30357
  });
30180
30358
  return customName;
@@ -30184,7 +30362,7 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
30184
30362
  }
30185
30363
  async function ensureExpandedContext(modelName, backendUrl) {
30186
30364
  if (modelName.startsWith("open-agents-")) {
30187
- const specs2 = detectSystemSpecs();
30365
+ const specs2 = await detectSystemSpecsAsync();
30188
30366
  const ctx2 = calculateContextWindow(specs2, 4);
30189
30367
  return { model: modelName, created: false, contextLabel: ctx2.label, numCtx: ctx2.numCtx };
30190
30368
  }
@@ -30195,7 +30373,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
30195
30373
  if (existing === null) {
30196
30374
  return { model: modelName, created: false, contextLabel: "", numCtx: 0 };
30197
30375
  }
30198
- const specs = detectSystemSpecs();
30376
+ const specs = await detectSystemSpecsAsync();
30199
30377
  if (typeof existing === "string") {
30200
30378
  let sizeGB2 = 4;
30201
30379
  try {
@@ -30213,13 +30391,13 @@ async function ensureExpandedContext(modelName, backendUrl) {
30213
30391
  } catch {
30214
30392
  }
30215
30393
  const ctx = calculateContextWindow(specs, sizeGB);
30216
- const created = createExpandedVariant(modelName, specs, sizeGB);
30394
+ const created = await createExpandedVariantAsync(modelName, specs, sizeGB);
30217
30395
  if (created) {
30218
30396
  return { model: created, created: true, contextLabel: ctx.label, numCtx: ctx.numCtx };
30219
30397
  }
30220
30398
  return { model: modelName, created: false, contextLabel: ctx.label, numCtx: ctx.numCtx };
30221
30399
  }
30222
- var QWEN_VARIANTS, TOOL_CALLING_MODELS, _cloudflaredInstallPromise;
30400
+ var execAsync, QWEN_VARIANTS, TOOL_CALLING_MODELS, _cloudflaredInstallPromise;
30223
30401
  var init_setup = __esm({
30224
30402
  "packages/cli/dist/tui/setup.js"() {
30225
30403
  "use strict";
@@ -30227,6 +30405,7 @@ var init_setup = __esm({
30227
30405
  init_render();
30228
30406
  init_config();
30229
30407
  init_dist();
30408
+ execAsync = promisify5(exec2);
30230
30409
  QWEN_VARIANTS = [
30231
30410
  { tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
30232
30411
  { tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
@@ -32105,17 +32284,17 @@ async function handleUpdate(subcommand, ctx) {
32105
32284
  try {
32106
32285
  const { createRequire: createRequire4 } = await import("node:module");
32107
32286
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
32108
- const { dirname: dirname19, join: join54 } = await import("node:path");
32109
- const { existsSync: existsSync40 } = await import("node:fs");
32287
+ const { dirname: dirname19, join: join55 } = await import("node:path");
32288
+ const { existsSync: existsSync41 } = await import("node:fs");
32110
32289
  const req = createRequire4(import.meta.url);
32111
32290
  const thisDir = dirname19(fileURLToPath14(import.meta.url));
32112
32291
  const candidates = [
32113
- join54(thisDir, "..", "package.json"),
32114
- join54(thisDir, "..", "..", "package.json"),
32115
- join54(thisDir, "..", "..", "..", "package.json")
32292
+ join55(thisDir, "..", "package.json"),
32293
+ join55(thisDir, "..", "..", "package.json"),
32294
+ join55(thisDir, "..", "..", "..", "package.json")
32116
32295
  ];
32117
32296
  for (const pkgPath of candidates) {
32118
- if (existsSync40(pkgPath)) {
32297
+ if (existsSync41(pkgPath)) {
32119
32298
  const pkg = req(pkgPath);
32120
32299
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
32121
32300
  currentVersion = pkg.version ?? "0.0.0";
@@ -32151,7 +32330,7 @@ async function handleUpdate(subcommand, ctx) {
32151
32330
  return;
32152
32331
  }
32153
32332
  checkSpinner.stop(`Update available: v${info.currentVersion} \u2192 v${c2.bold(c2.green(info.latestVersion))}`);
32154
- const { exec: exec2, execSync: es2 } = await import("node:child_process");
32333
+ const { exec: exec3, execSync: es2 } = await import("node:child_process");
32155
32334
  let needsSudo = false;
32156
32335
  try {
32157
32336
  const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
@@ -32180,7 +32359,7 @@ async function handleUpdate(subcommand, ctx) {
32180
32359
  let installOk = false;
32181
32360
  let installError = "";
32182
32361
  const runInstall2 = (cmd) => new Promise((resolve31) => {
32183
- const child = exec2(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
32362
+ const child = exec3(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
32184
32363
  if (err)
32185
32364
  installError = (stderr || err.message || "").trim();
32186
32365
  resolve31(!err);
@@ -32218,7 +32397,7 @@ async function handleUpdate(subcommand, ctx) {
32218
32397
  installSpinner.stop(`Update installed (v${info.latestVersion}).`);
32219
32398
  const rebuildSpinner = startInlineSpinner("Rebuilding native modules");
32220
32399
  const rebuildOk = await new Promise((resolve31) => {
32221
- const child = exec2(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
32400
+ const child = exec3(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
32222
32401
  child.stdout?.resume();
32223
32402
  child.stderr?.resume();
32224
32403
  });
@@ -32251,7 +32430,7 @@ async function handleUpdate(subcommand, ctx) {
32251
32430
  if (fsExists(venvPip)) {
32252
32431
  const pySpinner = startInlineSpinner("Upgrading Python venv packages");
32253
32432
  const pyOk = await new Promise((resolve31) => {
32254
- const child = exec2(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
32433
+ const child = exec3(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
32255
32434
  child.stdout?.resume();
32256
32435
  child.stderr?.resume();
32257
32436
  });
@@ -32400,8 +32579,8 @@ var init_commands = __esm({
32400
32579
  });
32401
32580
 
32402
32581
  // packages/cli/dist/tui/project-context.js
32403
- import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
32404
- import { join as join40, basename as basename10 } from "node:path";
32582
+ import { existsSync as existsSync31, readFileSync as readFileSync22, readdirSync as readdirSync8 } from "node:fs";
32583
+ import { join as join41, basename as basename10 } from "node:path";
32405
32584
  import { execSync as execSync26 } from "node:child_process";
32406
32585
  import { homedir as homedir11, platform as platform2, release } from "node:os";
32407
32586
  function getModelTier(modelName) {
@@ -32436,10 +32615,10 @@ function loadProjectMap(repoRoot) {
32436
32615
  if (!hasOaDirectory(repoRoot)) {
32437
32616
  initOaDirectory(repoRoot);
32438
32617
  }
32439
- const mapPath = join40(repoRoot, OA_DIR, "context", "project-map.md");
32440
- if (existsSync30(mapPath)) {
32618
+ const mapPath = join41(repoRoot, OA_DIR, "context", "project-map.md");
32619
+ if (existsSync31(mapPath)) {
32441
32620
  try {
32442
- const content = readFileSync21(mapPath, "utf-8");
32621
+ const content = readFileSync22(mapPath, "utf-8");
32443
32622
  return content;
32444
32623
  } catch {
32445
32624
  }
@@ -32480,31 +32659,31 @@ ${log}`);
32480
32659
  }
32481
32660
  function loadMemoryContext(repoRoot) {
32482
32661
  const sections = [];
32483
- const oaMemDir = join40(repoRoot, OA_DIR, "memory");
32662
+ const oaMemDir = join41(repoRoot, OA_DIR, "memory");
32484
32663
  const oaEntries = loadMemoryDir(oaMemDir, "project");
32485
32664
  if (oaEntries)
32486
32665
  sections.push(oaEntries);
32487
- const legacyMemDir = join40(repoRoot, ".open-agents", "memory");
32488
- if (legacyMemDir !== oaMemDir && existsSync30(legacyMemDir)) {
32666
+ const legacyMemDir = join41(repoRoot, ".open-agents", "memory");
32667
+ if (legacyMemDir !== oaMemDir && existsSync31(legacyMemDir)) {
32489
32668
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
32490
32669
  if (legacyEntries)
32491
32670
  sections.push(legacyEntries);
32492
32671
  }
32493
- const globalMemDir = join40(homedir11(), ".open-agents", "memory");
32672
+ const globalMemDir = join41(homedir11(), ".open-agents", "memory");
32494
32673
  const globalEntries = loadMemoryDir(globalMemDir, "global");
32495
32674
  if (globalEntries)
32496
32675
  sections.push(globalEntries);
32497
32676
  return sections.join("\n\n");
32498
32677
  }
32499
32678
  function loadMemoryDir(memDir, scope) {
32500
- if (!existsSync30(memDir))
32679
+ if (!existsSync31(memDir))
32501
32680
  return "";
32502
32681
  const lines = [];
32503
32682
  try {
32504
32683
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
32505
32684
  for (const file of files.slice(0, 10)) {
32506
32685
  try {
32507
- const raw = readFileSync21(join40(memDir, file), "utf-8");
32686
+ const raw = readFileSync22(join41(memDir, file), "utf-8");
32508
32687
  const entries = JSON.parse(raw);
32509
32688
  const topic = basename10(file, ".json");
32510
32689
  const keys = Object.keys(entries);
@@ -33408,11 +33587,7 @@ var init_carousel = __esm({
33408
33587
  process.stdout.write(`\x1B[${this.reservedRows + 1};1H`);
33409
33588
  this.resizeHandler = () => {
33410
33589
  this.width = process.stdout.columns ?? 80;
33411
- const newRows = process.stdout.rows ?? 24;
33412
33590
  this.rebuildRibbons();
33413
- if (this.started) {
33414
- process.stdout.write(`\x1B[${this.reservedRows + 1};${newRows}r`);
33415
- }
33416
33591
  };
33417
33592
  process.stdout.on("resize", this.resizeHandler);
33418
33593
  this.renderFrame();
@@ -33531,22 +33706,22 @@ var init_carousel = __esm({
33531
33706
  });
33532
33707
 
33533
33708
  // packages/cli/dist/tui/carousel-descriptors.js
33534
- import { existsSync as existsSync31, readFileSync as readFileSync22, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
33535
- import { join as join41, basename as basename11 } from "node:path";
33709
+ import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
33710
+ import { join as join42, basename as basename11 } from "node:path";
33536
33711
  function loadToolProfile(repoRoot) {
33537
- const filePath = join41(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
33712
+ const filePath = join42(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
33538
33713
  try {
33539
- if (!existsSync31(filePath))
33714
+ if (!existsSync32(filePath))
33540
33715
  return null;
33541
- return JSON.parse(readFileSync22(filePath, "utf-8"));
33716
+ return JSON.parse(readFileSync23(filePath, "utf-8"));
33542
33717
  } catch {
33543
33718
  return null;
33544
33719
  }
33545
33720
  }
33546
33721
  function saveToolProfile(repoRoot, profile) {
33547
- const contextDir = join41(repoRoot, OA_DIR, "context");
33722
+ const contextDir = join42(repoRoot, OA_DIR, "context");
33548
33723
  mkdirSync11(contextDir, { recursive: true });
33549
- writeFileSync11(join41(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
33724
+ writeFileSync12(join42(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
33550
33725
  }
33551
33726
  function categorizeToolCall(toolName) {
33552
33727
  for (const cat of TOOL_CATEGORIES) {
@@ -33604,25 +33779,25 @@ function weightedColor(profile) {
33604
33779
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
33605
33780
  }
33606
33781
  function loadCachedDescriptors(repoRoot) {
33607
- const filePath = join41(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
33782
+ const filePath = join42(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
33608
33783
  try {
33609
- if (!existsSync31(filePath))
33784
+ if (!existsSync32(filePath))
33610
33785
  return null;
33611
- const cached = JSON.parse(readFileSync22(filePath, "utf-8"));
33786
+ const cached = JSON.parse(readFileSync23(filePath, "utf-8"));
33612
33787
  return cached.phrases.length > 0 ? cached.phrases : null;
33613
33788
  } catch {
33614
33789
  return null;
33615
33790
  }
33616
33791
  }
33617
33792
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
33618
- const contextDir = join41(repoRoot, OA_DIR, "context");
33793
+ const contextDir = join42(repoRoot, OA_DIR, "context");
33619
33794
  mkdirSync11(contextDir, { recursive: true });
33620
33795
  const cached = {
33621
33796
  phrases,
33622
33797
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
33623
33798
  sourceHash
33624
33799
  };
33625
- writeFileSync11(join41(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
33800
+ writeFileSync12(join42(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
33626
33801
  }
33627
33802
  function generateDescriptors(repoRoot) {
33628
33803
  const profile = loadToolProfile(repoRoot);
@@ -33670,11 +33845,11 @@ function generateDescriptors(repoRoot) {
33670
33845
  return phrases;
33671
33846
  }
33672
33847
  function extractFromPackageJson(repoRoot, tags) {
33673
- const pkgPath = join41(repoRoot, "package.json");
33848
+ const pkgPath = join42(repoRoot, "package.json");
33674
33849
  try {
33675
- if (!existsSync31(pkgPath))
33850
+ if (!existsSync32(pkgPath))
33676
33851
  return;
33677
- const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
33852
+ const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
33678
33853
  if (pkg.name && typeof pkg.name === "string") {
33679
33854
  const parts = pkg.name.replace(/^@/, "").split("/");
33680
33855
  for (const p of parts)
@@ -33718,7 +33893,7 @@ function extractFromManifests(repoRoot, tags) {
33718
33893
  { file: ".github/workflows", tag: "ci/cd" }
33719
33894
  ];
33720
33895
  for (const check of manifestChecks) {
33721
- if (existsSync31(join41(repoRoot, check.file))) {
33896
+ if (existsSync32(join42(repoRoot, check.file))) {
33722
33897
  tags.push(check.tag);
33723
33898
  }
33724
33899
  }
@@ -33740,16 +33915,16 @@ function extractFromSessions(repoRoot, tags) {
33740
33915
  }
33741
33916
  }
33742
33917
  function extractFromMemory(repoRoot, tags) {
33743
- const memoryDir = join41(repoRoot, OA_DIR, "memory");
33918
+ const memoryDir = join42(repoRoot, OA_DIR, "memory");
33744
33919
  try {
33745
- if (!existsSync31(memoryDir))
33920
+ if (!existsSync32(memoryDir))
33746
33921
  return;
33747
33922
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
33748
33923
  for (const file of files) {
33749
33924
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
33750
33925
  tags.push(topic);
33751
33926
  try {
33752
- const data = JSON.parse(readFileSync22(join41(memoryDir, file), "utf-8"));
33927
+ const data = JSON.parse(readFileSync23(join42(memoryDir, file), "utf-8"));
33753
33928
  if (data && typeof data === "object") {
33754
33929
  const keys = Object.keys(data).slice(0, 3);
33755
33930
  for (const key of keys) {
@@ -33884,25 +34059,25 @@ var init_carousel_descriptors = __esm({
33884
34059
  });
33885
34060
 
33886
34061
  // packages/cli/dist/tui/voice.js
33887
- import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
33888
- import { join as join42 } from "node:path";
34062
+ import { existsSync as existsSync33, mkdirSync as mkdirSync12, writeFileSync as writeFileSync13, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
34063
+ import { join as join43 } from "node:path";
33889
34064
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
33890
34065
  import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
33891
34066
  import { createRequire } from "node:module";
33892
34067
  function voiceDir() {
33893
- return join42(homedir12(), ".open-agents", "voice");
34068
+ return join43(homedir12(), ".open-agents", "voice");
33894
34069
  }
33895
34070
  function modelsDir() {
33896
- return join42(voiceDir(), "models");
34071
+ return join43(voiceDir(), "models");
33897
34072
  }
33898
34073
  function modelDir(id) {
33899
- return join42(modelsDir(), id);
34074
+ return join43(modelsDir(), id);
33900
34075
  }
33901
34076
  function modelOnnxPath(id) {
33902
- return join42(modelDir(id), "model.onnx");
34077
+ return join43(modelDir(id), "model.onnx");
33903
34078
  }
33904
34079
  function modelConfigPath(id) {
33905
- return join42(modelDir(id), "config.json");
34080
+ return join43(modelDir(id), "config.json");
33906
34081
  }
33907
34082
  function emotionToPitchBias(emotion, stark = false, autist = false) {
33908
34083
  if (autist)
@@ -34762,11 +34937,11 @@ var init_voice = __esm({
34762
34937
  }
34763
34938
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
34764
34939
  }
34765
- const wavPath = join42(tmpdir6(), `oa-voice-${Date.now()}.wav`);
34940
+ const wavPath = join43(tmpdir6(), `oa-voice-${Date.now()}.wav`);
34766
34941
  this.writeWav(audioData, sampleRate, wavPath);
34767
34942
  await this.playWav(wavPath);
34768
34943
  try {
34769
- unlinkSync4(wavPath);
34944
+ unlinkSync5(wavPath);
34770
34945
  } catch {
34771
34946
  }
34772
34947
  }
@@ -34894,7 +35069,7 @@ var init_voice = __esm({
34894
35069
  return buffer;
34895
35070
  }
34896
35071
  writeWav(samples, sampleRate, path) {
34897
- writeFileSync12(path, this.buildWavBuffer(samples, sampleRate));
35072
+ writeFileSync13(path, this.buildWavBuffer(samples, sampleRate));
34898
35073
  }
34899
35074
  // -------------------------------------------------------------------------
34900
35075
  // Audio playback (system default speakers)
@@ -35053,7 +35228,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35053
35228
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
35054
35229
  const mlxVoice = model.mlxVoice ?? "af_heart";
35055
35230
  const mlxLangCode = model.mlxLangCode ?? "a";
35056
- const wavPath = join42(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
35231
+ const wavPath = join43(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
35057
35232
  const pyScript = [
35058
35233
  "import sys, json",
35059
35234
  "from mlx_audio.tts import generate as tts_gen",
@@ -35070,11 +35245,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35070
35245
  return;
35071
35246
  }
35072
35247
  }
35073
- if (!existsSync32(wavPath))
35248
+ if (!existsSync33(wavPath))
35074
35249
  return;
35075
35250
  if (volume !== 1) {
35076
35251
  try {
35077
- const wavData = readFileSync23(wavPath);
35252
+ const wavData = readFileSync24(wavPath);
35078
35253
  if (wavData.length > 44) {
35079
35254
  const header = wavData.subarray(0, 44);
35080
35255
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -35082,14 +35257,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35082
35257
  samples[i] = Math.round(samples[i] * volume);
35083
35258
  }
35084
35259
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
35085
- writeFileSync12(wavPath, scaled);
35260
+ writeFileSync13(wavPath, scaled);
35086
35261
  }
35087
35262
  } catch {
35088
35263
  }
35089
35264
  }
35090
35265
  if (this.onPCMOutput) {
35091
35266
  try {
35092
- const wavData = readFileSync23(wavPath);
35267
+ const wavData = readFileSync24(wavPath);
35093
35268
  if (wavData.length > 44) {
35094
35269
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
35095
35270
  const sampleRate = wavData.readUInt32LE(24);
@@ -35100,7 +35275,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35100
35275
  }
35101
35276
  await this.playWav(wavPath);
35102
35277
  try {
35103
- unlinkSync4(wavPath);
35278
+ unlinkSync5(wavPath);
35104
35279
  } catch {
35105
35280
  }
35106
35281
  }
@@ -35121,7 +35296,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35121
35296
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
35122
35297
  const mlxVoice = model.mlxVoice ?? "af_heart";
35123
35298
  const mlxLangCode = model.mlxLangCode ?? "a";
35124
- const wavPath = join42(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
35299
+ const wavPath = join43(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
35125
35300
  const pyScript = [
35126
35301
  "import sys, json",
35127
35302
  "from mlx_audio.tts import generate as tts_gen",
@@ -35138,11 +35313,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35138
35313
  return null;
35139
35314
  }
35140
35315
  }
35141
- if (!existsSync32(wavPath))
35316
+ if (!existsSync33(wavPath))
35142
35317
  return null;
35143
35318
  try {
35144
- const data = readFileSync23(wavPath);
35145
- unlinkSync4(wavPath);
35319
+ const data = readFileSync24(wavPath);
35320
+ unlinkSync5(wavPath);
35146
35321
  return data;
35147
35322
  } catch {
35148
35323
  return null;
@@ -35156,40 +35331,40 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35156
35331
  return;
35157
35332
  const arch = process.arch;
35158
35333
  mkdirSync12(voiceDir(), { recursive: true });
35159
- const pkgPath = join42(voiceDir(), "package.json");
35334
+ const pkgPath = join43(voiceDir(), "package.json");
35160
35335
  const expectedDeps = {
35161
35336
  "onnxruntime-node": "^1.21.0",
35162
35337
  "phonemizer": "^1.2.1"
35163
35338
  };
35164
- if (existsSync32(pkgPath)) {
35339
+ if (existsSync33(pkgPath)) {
35165
35340
  try {
35166
- const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
35341
+ const existing = JSON.parse(readFileSync24(pkgPath, "utf8"));
35167
35342
  if (!existing.dependencies?.["phonemizer"]) {
35168
35343
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
35169
- writeFileSync12(pkgPath, JSON.stringify(existing, null, 2));
35344
+ writeFileSync13(pkgPath, JSON.stringify(existing, null, 2));
35170
35345
  }
35171
35346
  } catch {
35172
35347
  }
35173
35348
  }
35174
- if (!existsSync32(pkgPath)) {
35175
- writeFileSync12(pkgPath, JSON.stringify({
35349
+ if (!existsSync33(pkgPath)) {
35350
+ writeFileSync13(pkgPath, JSON.stringify({
35176
35351
  name: "open-agents-voice",
35177
35352
  private: true,
35178
35353
  dependencies: expectedDeps
35179
35354
  }, null, 2));
35180
35355
  }
35181
- const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
35356
+ const voiceRequire = createRequire(join43(voiceDir(), "index.js"));
35182
35357
  const probeOnnx = () => {
35183
35358
  try {
35184
- const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
35359
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join43(voiceDir(), "node_modules") } });
35185
35360
  const output = result.toString().trim();
35186
35361
  return output === "OK";
35187
35362
  } catch {
35188
35363
  return false;
35189
35364
  }
35190
35365
  };
35191
- const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
35192
- const onnxInstalled = existsSync32(onnxNodeModules);
35366
+ const onnxNodeModules = join43(voiceDir(), "node_modules", "onnxruntime-node");
35367
+ const onnxInstalled = existsSync33(onnxNodeModules);
35193
35368
  if (onnxInstalled && !probeOnnx()) {
35194
35369
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
35195
35370
  }
@@ -35247,18 +35422,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
35247
35422
  const dir = modelDir(id);
35248
35423
  const onnxPath = modelOnnxPath(id);
35249
35424
  const configPath = modelConfigPath(id);
35250
- if (existsSync32(onnxPath) && existsSync32(configPath))
35425
+ if (existsSync33(onnxPath) && existsSync33(configPath))
35251
35426
  return;
35252
35427
  mkdirSync12(dir, { recursive: true });
35253
- if (!existsSync32(configPath)) {
35428
+ if (!existsSync33(configPath)) {
35254
35429
  renderInfo(`Downloading ${model.label} voice config...`);
35255
35430
  const configResp = await fetch(model.configUrl);
35256
35431
  if (!configResp.ok)
35257
35432
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
35258
35433
  const configText = await configResp.text();
35259
- writeFileSync12(configPath, configText);
35434
+ writeFileSync13(configPath, configText);
35260
35435
  }
35261
- if (!existsSync32(onnxPath)) {
35436
+ if (!existsSync33(onnxPath)) {
35262
35437
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
35263
35438
  const onnxResp = await fetch(model.onnxUrl);
35264
35439
  if (!onnxResp.ok)
@@ -35283,7 +35458,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
35283
35458
  }
35284
35459
  }
35285
35460
  const fullBuffer = Buffer.concat(chunks);
35286
- writeFileSync12(onnxPath, fullBuffer);
35461
+ writeFileSync13(onnxPath, fullBuffer);
35287
35462
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
35288
35463
  }
35289
35464
  }
@@ -35295,10 +35470,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
35295
35470
  throw new Error("ONNX runtime not loaded");
35296
35471
  const onnxPath = modelOnnxPath(this.modelId);
35297
35472
  const configPath = modelConfigPath(this.modelId);
35298
- if (!existsSync32(onnxPath) || !existsSync32(configPath)) {
35473
+ if (!existsSync33(onnxPath) || !existsSync33(configPath)) {
35299
35474
  throw new Error(`Model files not found for ${this.modelId}`);
35300
35475
  }
35301
- this.config = JSON.parse(readFileSync23(configPath, "utf8"));
35476
+ this.config = JSON.parse(readFileSync24(configPath, "utf8"));
35302
35477
  this.session = await this.ort.InferenceSession.create(onnxPath, {
35303
35478
  executionProviders: ["cpu"],
35304
35479
  graphOptimizationLevel: "all"
@@ -36160,10 +36335,10 @@ var init_stream_renderer = __esm({
36160
36335
 
36161
36336
  // packages/cli/dist/tui/edit-history.js
36162
36337
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync13 } from "node:fs";
36163
- import { join as join43 } from "node:path";
36338
+ import { join as join44 } from "node:path";
36164
36339
  function createEditHistoryLogger(repoRoot, sessionId) {
36165
- const historyDir = join43(repoRoot, ".oa", "history");
36166
- const logPath = join43(historyDir, "edits.jsonl");
36340
+ const historyDir = join44(repoRoot, ".oa", "history");
36341
+ const logPath = join44(historyDir, "edits.jsonl");
36167
36342
  try {
36168
36343
  mkdirSync13(historyDir, { recursive: true });
36169
36344
  } catch {
@@ -36274,17 +36449,17 @@ var init_edit_history = __esm({
36274
36449
  });
36275
36450
 
36276
36451
  // packages/cli/dist/tui/promptLoader.js
36277
- import { readFileSync as readFileSync24, existsSync as existsSync33 } from "node:fs";
36278
- import { join as join44, dirname as dirname16 } from "node:path";
36452
+ import { readFileSync as readFileSync25, existsSync as existsSync34 } from "node:fs";
36453
+ import { join as join45, dirname as dirname16 } from "node:path";
36279
36454
  import { fileURLToPath as fileURLToPath11 } from "node:url";
36280
36455
  function loadPrompt3(promptPath, vars) {
36281
36456
  let content = cache3.get(promptPath);
36282
36457
  if (content === void 0) {
36283
- const fullPath = join44(PROMPTS_DIR3, promptPath);
36284
- if (!existsSync33(fullPath)) {
36458
+ const fullPath = join45(PROMPTS_DIR3, promptPath);
36459
+ if (!existsSync34(fullPath)) {
36285
36460
  throw new Error(`Prompt file not found: ${fullPath}`);
36286
36461
  }
36287
- content = readFileSync24(fullPath, "utf-8");
36462
+ content = readFileSync25(fullPath, "utf-8");
36288
36463
  cache3.set(promptPath, content);
36289
36464
  }
36290
36465
  if (!vars)
@@ -36297,23 +36472,23 @@ var init_promptLoader3 = __esm({
36297
36472
  "use strict";
36298
36473
  __filename3 = fileURLToPath11(import.meta.url);
36299
36474
  __dirname6 = dirname16(__filename3);
36300
- devPath2 = join44(__dirname6, "..", "..", "prompts");
36301
- publishedPath2 = join44(__dirname6, "..", "prompts");
36302
- PROMPTS_DIR3 = existsSync33(devPath2) ? devPath2 : publishedPath2;
36475
+ devPath2 = join45(__dirname6, "..", "..", "prompts");
36476
+ publishedPath2 = join45(__dirname6, "..", "prompts");
36477
+ PROMPTS_DIR3 = existsSync34(devPath2) ? devPath2 : publishedPath2;
36303
36478
  cache3 = /* @__PURE__ */ new Map();
36304
36479
  }
36305
36480
  });
36306
36481
 
36307
36482
  // packages/cli/dist/tui/dream-engine.js
36308
- import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
36309
- import { join as join45, basename as basename12 } from "node:path";
36483
+ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
36484
+ import { join as join46, basename as basename12 } from "node:path";
36310
36485
  import { execSync as execSync28 } from "node:child_process";
36311
36486
  function loadAutoresearchMemory(repoRoot) {
36312
- const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
36313
- if (!existsSync34(memoryPath))
36487
+ const memoryPath = join46(repoRoot, ".oa", "memory", "autoresearch.json");
36488
+ if (!existsSync35(memoryPath))
36314
36489
  return "";
36315
36490
  try {
36316
- const raw = readFileSync25(memoryPath, "utf-8");
36491
+ const raw = readFileSync26(memoryPath, "utf-8");
36317
36492
  const data = JSON.parse(raw);
36318
36493
  const sections = [];
36319
36494
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -36503,14 +36678,14 @@ var init_dream_engine = __esm({
36503
36678
  const content = String(args["content"] ?? "");
36504
36679
  if (!rawPath)
36505
36680
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
36506
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
36681
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
36507
36682
  if (!targetPath.startsWith(this.autoresearchDir)) {
36508
36683
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
36509
36684
  }
36510
36685
  try {
36511
- const dir = join45(targetPath, "..");
36686
+ const dir = join46(targetPath, "..");
36512
36687
  mkdirSync14(dir, { recursive: true });
36513
- writeFileSync13(targetPath, content, "utf-8");
36688
+ writeFileSync14(targetPath, content, "utf-8");
36514
36689
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
36515
36690
  } catch (err) {
36516
36691
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -36538,20 +36713,20 @@ var init_dream_engine = __esm({
36538
36713
  const rawPath = String(args["path"] ?? "");
36539
36714
  const oldStr = String(args["old_string"] ?? "");
36540
36715
  const newStr = String(args["new_string"] ?? "");
36541
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
36716
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
36542
36717
  if (!targetPath.startsWith(this.autoresearchDir)) {
36543
36718
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
36544
36719
  }
36545
36720
  try {
36546
- if (!existsSync34(targetPath)) {
36721
+ if (!existsSync35(targetPath)) {
36547
36722
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
36548
36723
  }
36549
- let content = readFileSync25(targetPath, "utf-8");
36724
+ let content = readFileSync26(targetPath, "utf-8");
36550
36725
  if (!content.includes(oldStr)) {
36551
36726
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
36552
36727
  }
36553
36728
  content = content.replace(oldStr, newStr);
36554
- writeFileSync13(targetPath, content, "utf-8");
36729
+ writeFileSync14(targetPath, content, "utf-8");
36555
36730
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
36556
36731
  } catch (err) {
36557
36732
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -36592,14 +36767,14 @@ var init_dream_engine = __esm({
36592
36767
  const content = String(args["content"] ?? "");
36593
36768
  if (!rawPath)
36594
36769
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
36595
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
36770
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
36596
36771
  if (!targetPath.startsWith(this.dreamsDir)) {
36597
36772
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
36598
36773
  }
36599
36774
  try {
36600
- const dir = join45(targetPath, "..");
36775
+ const dir = join46(targetPath, "..");
36601
36776
  mkdirSync14(dir, { recursive: true });
36602
- writeFileSync13(targetPath, content, "utf-8");
36777
+ writeFileSync14(targetPath, content, "utf-8");
36603
36778
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
36604
36779
  } catch (err) {
36605
36780
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -36627,20 +36802,20 @@ var init_dream_engine = __esm({
36627
36802
  const rawPath = String(args["path"] ?? "");
36628
36803
  const oldStr = String(args["old_string"] ?? "");
36629
36804
  const newStr = String(args["new_string"] ?? "");
36630
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
36805
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
36631
36806
  if (!targetPath.startsWith(this.dreamsDir)) {
36632
36807
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
36633
36808
  }
36634
36809
  try {
36635
- if (!existsSync34(targetPath)) {
36810
+ if (!existsSync35(targetPath)) {
36636
36811
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
36637
36812
  }
36638
- let content = readFileSync25(targetPath, "utf-8");
36813
+ let content = readFileSync26(targetPath, "utf-8");
36639
36814
  if (!content.includes(oldStr)) {
36640
36815
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
36641
36816
  }
36642
36817
  content = content.replace(oldStr, newStr);
36643
- writeFileSync13(targetPath, content, "utf-8");
36818
+ writeFileSync14(targetPath, content, "utf-8");
36644
36819
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
36645
36820
  } catch (err) {
36646
36821
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -36694,7 +36869,7 @@ var init_dream_engine = __esm({
36694
36869
  constructor(config, repoRoot) {
36695
36870
  this.config = config;
36696
36871
  this.repoRoot = repoRoot;
36697
- this.dreamsDir = join45(repoRoot, ".oa", "dreams");
36872
+ this.dreamsDir = join46(repoRoot, ".oa", "dreams");
36698
36873
  this.state = {
36699
36874
  mode: "default",
36700
36875
  active: false,
@@ -36778,8 +36953,8 @@ ${result.summary}`;
36778
36953
  if (mode !== "default" || cycle === totalCycles) {
36779
36954
  renderDreamContraction(cycle);
36780
36955
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
36781
- const summaryPath = join45(this.dreamsDir, `cycle-${cycle}-summary.md`);
36782
- writeFileSync13(summaryPath, cycleSummary, "utf-8");
36956
+ const summaryPath = join46(this.dreamsDir, `cycle-${cycle}-summary.md`);
36957
+ writeFileSync14(summaryPath, cycleSummary, "utf-8");
36783
36958
  }
36784
36959
  if (mode === "lucid" && !this.abortController.signal.aborted) {
36785
36960
  this.saveVersionCheckpoint(cycle);
@@ -36991,7 +37166,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
36991
37166
  }
36992
37167
  /** Build role-specific tool sets for swarm agents */
36993
37168
  buildSwarmTools(role, _workspace) {
36994
- const autoresearchDir = join45(this.repoRoot, ".oa", "autoresearch");
37169
+ const autoresearchDir = join46(this.repoRoot, ".oa", "autoresearch");
36995
37170
  const taskComplete = this.createSwarmTaskCompleteTool(role);
36996
37171
  switch (role) {
36997
37172
  case "researcher": {
@@ -37355,7 +37530,7 @@ INSTRUCTIONS:
37355
37530
  2. Summarize the key learnings and next steps
37356
37531
 
37357
37532
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
37358
- const reportPath = join45(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
37533
+ const reportPath = join46(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
37359
37534
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
37360
37535
 
37361
37536
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -37378,7 +37553,7 @@ ${summaryResult}
37378
37553
  `;
37379
37554
  try {
37380
37555
  mkdirSync14(this.dreamsDir, { recursive: true });
37381
- writeFileSync13(reportPath, report, "utf-8");
37556
+ writeFileSync14(reportPath, report, "utf-8");
37382
37557
  } catch {
37383
37558
  }
37384
37559
  renderSwarmComplete(workspace);
@@ -37444,7 +37619,7 @@ ${summaryResult}
37444
37619
  }
37445
37620
  /** Save workspace backup for lucid mode */
37446
37621
  saveVersionCheckpoint(cycle) {
37447
- const checkpointDir = join45(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
37622
+ const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
37448
37623
  try {
37449
37624
  mkdirSync14(checkpointDir, { recursive: true });
37450
37625
  try {
@@ -37463,10 +37638,10 @@ ${summaryResult}
37463
37638
  encoding: "utf-8",
37464
37639
  timeout: 5e3
37465
37640
  }).trim();
37466
- writeFileSync13(join45(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
37467
- writeFileSync13(join45(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
37468
- writeFileSync13(join45(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
37469
- writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({
37641
+ writeFileSync14(join46(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
37642
+ writeFileSync14(join46(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
37643
+ writeFileSync14(join46(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
37644
+ writeFileSync14(join46(checkpointDir, "checkpoint.json"), JSON.stringify({
37470
37645
  cycle,
37471
37646
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
37472
37647
  gitHash,
@@ -37474,7 +37649,7 @@ ${summaryResult}
37474
37649
  }, null, 2), "utf-8");
37475
37650
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
37476
37651
  } catch {
37477
- writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
37652
+ writeFileSync14(join46(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
37478
37653
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
37479
37654
  }
37480
37655
  } catch (err) {
@@ -37532,14 +37707,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
37532
37707
  ---
37533
37708
  *Auto-generated by open-agents dream engine*
37534
37709
  `;
37535
- writeFileSync13(join45(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
37710
+ writeFileSync14(join46(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
37536
37711
  } catch {
37537
37712
  }
37538
37713
  }
37539
37714
  /** Save dream state for resume/inspection */
37540
37715
  saveDreamState() {
37541
37716
  try {
37542
- writeFileSync13(join45(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
37717
+ writeFileSync14(join46(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
37543
37718
  } catch {
37544
37719
  }
37545
37720
  }
@@ -37913,8 +38088,8 @@ var init_bless_engine = __esm({
37913
38088
  });
37914
38089
 
37915
38090
  // packages/cli/dist/tui/dmn-engine.js
37916
- import { existsSync as existsSync35, readFileSync as readFileSync26, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
37917
- import { join as join46, basename as basename13 } from "node:path";
38091
+ import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync6 } from "node:fs";
38092
+ import { join as join47, basename as basename13 } from "node:path";
37918
38093
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
37919
38094
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
37920
38095
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -38027,8 +38202,8 @@ var init_dmn_engine = __esm({
38027
38202
  constructor(config, repoRoot) {
38028
38203
  this.config = config;
38029
38204
  this.repoRoot = repoRoot;
38030
- this.stateDir = join46(repoRoot, ".oa", "dmn");
38031
- this.historyDir = join46(repoRoot, ".oa", "dmn", "cycles");
38205
+ this.stateDir = join47(repoRoot, ".oa", "dmn");
38206
+ this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
38032
38207
  mkdirSync15(this.historyDir, { recursive: true });
38033
38208
  this.loadState();
38034
38209
  }
@@ -38618,11 +38793,11 @@ OUTPUT: Call task_complete with JSON:
38618
38793
  async gatherMemoryTopics() {
38619
38794
  const topics = [];
38620
38795
  const dirs = [
38621
- join46(this.repoRoot, ".oa", "memory"),
38622
- join46(this.repoRoot, ".open-agents", "memory")
38796
+ join47(this.repoRoot, ".oa", "memory"),
38797
+ join47(this.repoRoot, ".open-agents", "memory")
38623
38798
  ];
38624
38799
  for (const dir of dirs) {
38625
- if (!existsSync35(dir))
38800
+ if (!existsSync36(dir))
38626
38801
  continue;
38627
38802
  try {
38628
38803
  const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
@@ -38638,29 +38813,29 @@ OUTPUT: Call task_complete with JSON:
38638
38813
  }
38639
38814
  // ── State persistence ─────────────────────────────────────────────────
38640
38815
  loadState() {
38641
- const path = join46(this.stateDir, "state.json");
38642
- if (existsSync35(path)) {
38816
+ const path = join47(this.stateDir, "state.json");
38817
+ if (existsSync36(path)) {
38643
38818
  try {
38644
- this.state = JSON.parse(readFileSync26(path, "utf-8"));
38819
+ this.state = JSON.parse(readFileSync27(path, "utf-8"));
38645
38820
  } catch {
38646
38821
  }
38647
38822
  }
38648
38823
  }
38649
38824
  saveState() {
38650
38825
  try {
38651
- writeFileSync14(join46(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
38826
+ writeFileSync15(join47(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
38652
38827
  } catch {
38653
38828
  }
38654
38829
  }
38655
38830
  saveCycleResult(result) {
38656
38831
  try {
38657
38832
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
38658
- writeFileSync14(join46(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
38833
+ writeFileSync15(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
38659
38834
  const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
38660
38835
  if (files.length > 50) {
38661
38836
  for (const old of files.slice(0, files.length - 50)) {
38662
38837
  try {
38663
- unlinkSync5(join46(this.historyDir, old));
38838
+ unlinkSync6(join47(this.historyDir, old));
38664
38839
  } catch {
38665
38840
  }
38666
38841
  }
@@ -38673,8 +38848,8 @@ OUTPUT: Call task_complete with JSON:
38673
38848
  });
38674
38849
 
38675
38850
  // packages/cli/dist/tui/snr-engine.js
38676
- import { existsSync as existsSync36, readdirSync as readdirSync12, readFileSync as readFileSync27 } from "node:fs";
38677
- import { join as join47, basename as basename14 } from "node:path";
38851
+ import { existsSync as existsSync37, readdirSync as readdirSync12, readFileSync as readFileSync28 } from "node:fs";
38852
+ import { join as join48, basename as basename14 } from "node:path";
38678
38853
  function computeDPrime(signalScores, noiseScores) {
38679
38854
  if (signalScores.length === 0 || noiseScores.length === 0)
38680
38855
  return 0;
@@ -38914,11 +39089,11 @@ Call task_complete with the JSON array when done.`, onEvent)
38914
39089
  loadMemoryEntries(topics) {
38915
39090
  const entries = [];
38916
39091
  const dirs = [
38917
- join47(this.repoRoot, ".oa", "memory"),
38918
- join47(this.repoRoot, ".open-agents", "memory")
39092
+ join48(this.repoRoot, ".oa", "memory"),
39093
+ join48(this.repoRoot, ".open-agents", "memory")
38919
39094
  ];
38920
39095
  for (const dir of dirs) {
38921
- if (!existsSync36(dir))
39096
+ if (!existsSync37(dir))
38922
39097
  continue;
38923
39098
  try {
38924
39099
  const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
@@ -38927,7 +39102,7 @@ Call task_complete with the JSON array when done.`, onEvent)
38927
39102
  if (topics.length > 0 && !topics.includes(topic))
38928
39103
  continue;
38929
39104
  try {
38930
- const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
39105
+ const data = JSON.parse(readFileSync28(join48(dir, f), "utf-8"));
38931
39106
  for (const [key, val] of Object.entries(data)) {
38932
39107
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
38933
39108
  entries.push({ topic, key, value });
@@ -39494,8 +39669,8 @@ var init_tool_policy = __esm({
39494
39669
  });
39495
39670
 
39496
39671
  // packages/cli/dist/tui/telegram-bridge.js
39497
- import { mkdirSync as mkdirSync16, existsSync as existsSync37, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
39498
- import { join as join48, resolve as resolve27 } from "node:path";
39672
+ import { mkdirSync as mkdirSync16, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
39673
+ import { join as join49, resolve as resolve27 } from "node:path";
39499
39674
  import { writeFile as writeFileAsync } from "node:fs/promises";
39500
39675
  function convertMarkdownToTelegramHTML(md) {
39501
39676
  let html = md;
@@ -40260,7 +40435,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
40260
40435
  return null;
40261
40436
  const buffer = Buffer.from(await res.arrayBuffer());
40262
40437
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
40263
- const localPath = join48(this.mediaCacheDir, fileName);
40438
+ const localPath = join49(this.mediaCacheDir, fileName);
40264
40439
  await writeFileAsync(localPath, buffer);
40265
40440
  return localPath;
40266
40441
  } catch {
@@ -40348,7 +40523,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
40348
40523
  for (const [key, entry] of this.mediaCache) {
40349
40524
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
40350
40525
  try {
40351
- unlinkSync6(entry.localPath);
40526
+ unlinkSync7(entry.localPath);
40352
40527
  } catch {
40353
40528
  }
40354
40529
  this.mediaCache.delete(key);
@@ -42093,11 +42268,11 @@ var init_status_bar = __esm({
42093
42268
  import * as readline2 from "node:readline";
42094
42269
  import { Writable } from "node:stream";
42095
42270
  import { cwd } from "node:process";
42096
- import { resolve as resolve28, join as join49, dirname as dirname17, extname as extname9 } from "node:path";
42271
+ import { resolve as resolve28, join as join50, dirname as dirname17, extname as extname9 } from "node:path";
42097
42272
  import { createRequire as createRequire2 } from "node:module";
42098
42273
  import { fileURLToPath as fileURLToPath12 } from "node:url";
42099
- import { readFileSync as readFileSync28, writeFileSync as writeFileSync15, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
42100
- import { existsSync as existsSync38 } from "node:fs";
42274
+ import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
42275
+ import { existsSync as existsSync39 } from "node:fs";
42101
42276
  import { homedir as homedir13 } from "node:os";
42102
42277
  function formatTimeAgo(date) {
42103
42278
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -42117,12 +42292,12 @@ function getVersion3() {
42117
42292
  const require2 = createRequire2(import.meta.url);
42118
42293
  const thisDir = dirname17(fileURLToPath12(import.meta.url));
42119
42294
  const candidates = [
42120
- join49(thisDir, "..", "package.json"),
42121
- join49(thisDir, "..", "..", "package.json"),
42122
- join49(thisDir, "..", "..", "..", "package.json")
42295
+ join50(thisDir, "..", "package.json"),
42296
+ join50(thisDir, "..", "..", "package.json"),
42297
+ join50(thisDir, "..", "..", "..", "package.json")
42123
42298
  ];
42124
42299
  for (const pkgPath of candidates) {
42125
- if (existsSync38(pkgPath)) {
42300
+ if (existsSync39(pkgPath)) {
42126
42301
  const pkg = require2(pkgPath);
42127
42302
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
42128
42303
  return pkg.version ?? "0.0.0";
@@ -42328,15 +42503,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
42328
42503
  function gatherMemorySnippets(root) {
42329
42504
  const snippets = [];
42330
42505
  const dirs = [
42331
- join49(root, ".oa", "memory"),
42332
- join49(root, ".open-agents", "memory")
42506
+ join50(root, ".oa", "memory"),
42507
+ join50(root, ".open-agents", "memory")
42333
42508
  ];
42334
42509
  for (const dir of dirs) {
42335
- if (!existsSync38(dir))
42510
+ if (!existsSync39(dir))
42336
42511
  continue;
42337
42512
  try {
42338
42513
  for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
42339
- const data = JSON.parse(readFileSync28(join49(dir, f), "utf-8"));
42514
+ const data = JSON.parse(readFileSync29(join50(dir, f), "utf-8"));
42340
42515
  for (const val of Object.values(data)) {
42341
42516
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
42342
42517
  if (v.length > 10)
@@ -42690,7 +42865,7 @@ ${entry.fullContent}`
42690
42865
  const sizeStr = resultLen > 0 ? ` | ${resultLen.toLocaleString()} chars (~${Math.ceil(resultLen / 4).toLocaleString()} tokens)` : "";
42691
42866
  renderVerbose(`${event.toolName ?? "unknown"}: ${durStr}${sizeStr}`);
42692
42867
  }
42693
- if (voice?.enabled) {
42868
+ if (voice?.enabled && event.toolName !== "task_complete") {
42694
42869
  const emoState2 = emotionEngine?.getState();
42695
42870
  const emoCtx2 = emoState2 ? { valence: emoState2.valence, arousal: emoState2.arousal, label: emoState2.label, emoji: emoState2.emoji } : void 0;
42696
42871
  const desc = describeToolResult(event.toolName ?? "unknown", event.success ?? false, vLevel, event.content ?? void 0, emoCtx2, isStark);
@@ -42926,48 +43101,14 @@ async function startInteractive(config, repoPath) {
42926
43101
  setEmojisEnabled(savedSettings.emojis);
42927
43102
  if (savedSettings.colors !== void 0)
42928
43103
  setColorsEnabled(savedSettings.colors);
42929
- if (!isResumed) {
42930
- const needsSetup = isFirstRun() || !await isModelAvailable(config);
42931
- if (needsSetup && config.backendType === "ollama") {
43104
+ if (!isResumed && isFirstRun() && config.backendType === "ollama") {
43105
+ const needsSetup = !await isModelAvailable(config);
43106
+ if (needsSetup) {
42932
43107
  const setupModel = await runSetupWizard(config);
42933
43108
  const freshConfig = loadConfig();
42934
43109
  config = { ...config, ...freshConfig, model: setupModel ?? freshConfig.model };
42935
43110
  }
42936
43111
  }
42937
- if (config.backendType === "ollama" && !config.model.startsWith("open-agents-")) {
42938
- try {
42939
- const expandResult = await ensureExpandedContext(config.model, config.backendUrl);
42940
- if (expandResult.created) {
42941
- renderInfo(`Created expanded context model: ${expandResult.model} (${expandResult.contextLabel}, ${expandResult.numCtx} tokens)`);
42942
- config = { ...config, model: expandResult.model };
42943
- } else if (expandResult.model !== config.model) {
42944
- renderInfo(`Using expanded context model: ${expandResult.model} (${expandResult.contextLabel})`);
42945
- config = { ...config, model: expandResult.model };
42946
- }
42947
- } catch {
42948
- }
42949
- }
42950
- if (!isResumed) {
42951
- try {
42952
- const baseUrl = normalizeBaseUrl(config.backendUrl);
42953
- const provider2 = detectProvider(config.backendUrl);
42954
- const healthUrl = `${baseUrl}${provider2.modelsPath}`;
42955
- const headers = {};
42956
- if (config.apiKey) {
42957
- headers["Authorization"] = `Bearer ${config.apiKey}`;
42958
- }
42959
- const resp = await fetch(healthUrl, { headers, signal: AbortSignal.timeout(1e4) });
42960
- if (!resp.ok)
42961
- throw new Error(`HTTP ${resp.status}`);
42962
- } catch {
42963
- const provider2 = detectProvider(config.backendUrl);
42964
- renderWarning(`Cannot reach ${provider2.label} at ${config.backendUrl}`);
42965
- if (provider2.id === "ollama") {
42966
- renderInfo("Use /endpoint http://127.0.0.1:11434 to auto-install & start Ollama.");
42967
- }
42968
- renderInfo("Use /endpoint to configure a different backend. Starting anyway...");
42969
- }
42970
- }
42971
43112
  let carouselPhrases = null;
42972
43113
  try {
42973
43114
  carouselPhrases = loadCachedDescriptors(repoRoot) ?? generateDescriptors(repoRoot);
@@ -43102,7 +43243,7 @@ async function startInteractive(config, repoPath) {
43102
43243
  let exposeGateway = null;
43103
43244
  let peerMesh = null;
43104
43245
  let inferenceRouter = null;
43105
- const secretVault = new SecretVault(join49(repoRoot, ".oa", "vault.enc"));
43246
+ const secretVault = new SecretVault(join50(repoRoot, ".oa", "vault.enc"));
43106
43247
  let adminSessionKey = null;
43107
43248
  const callSubAgents = /* @__PURE__ */ new Map();
43108
43249
  const streamRenderer = new StreamRenderer();
@@ -43307,13 +43448,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
43307
43448
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
43308
43449
  return [hits, line];
43309
43450
  }
43310
- const HISTORY_DIR = join49(homedir13(), ".open-agents");
43311
- const HISTORY_FILE = join49(HISTORY_DIR, "repl-history");
43451
+ const HISTORY_DIR = join50(homedir13(), ".open-agents");
43452
+ const HISTORY_FILE = join50(HISTORY_DIR, "repl-history");
43312
43453
  const MAX_HISTORY_LINES = 500;
43313
43454
  let savedHistory = [];
43314
43455
  try {
43315
- if (existsSync38(HISTORY_FILE)) {
43316
- const raw = readFileSync28(HISTORY_FILE, "utf8").trim();
43456
+ if (existsSync39(HISTORY_FILE)) {
43457
+ const raw = readFileSync29(HISTORY_FILE, "utf8").trim();
43317
43458
  if (raw)
43318
43459
  savedHistory = raw.split("\n").reverse();
43319
43460
  }
@@ -43335,9 +43476,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
43335
43476
  mkdirSync17(HISTORY_DIR, { recursive: true });
43336
43477
  appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
43337
43478
  if (Math.random() < 0.02) {
43338
- const all = readFileSync28(HISTORY_FILE, "utf8").trim().split("\n");
43479
+ const all = readFileSync29(HISTORY_FILE, "utf8").trim().split("\n");
43339
43480
  if (all.length > MAX_HISTORY_LINES) {
43340
- writeFileSync15(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
43481
+ writeFileSync16(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
43341
43482
  }
43342
43483
  }
43343
43484
  } catch {
@@ -43358,8 +43499,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
43358
43499
  const termRows = process.stdout.rows ?? 24;
43359
43500
  const scrollStart = carousel.reservedRows + 1;
43360
43501
  const scrollEnd = Math.max(termRows - statusBar.reservedRows, scrollStart + 1);
43361
- process.stdout.write(`\x1B[${scrollStart};${scrollEnd}r`);
43362
- process.stdout.write(`\x1B[${scrollStart};1H\x1B[J`);
43502
+ let clearBuf = "";
43503
+ for (let r = scrollStart; r <= scrollEnd; r++) {
43504
+ clearBuf += `\x1B[${r};1H\x1B[2K`;
43505
+ }
43506
+ process.stdout.write(clearBuf);
43363
43507
  renderRichHeader({
43364
43508
  model: currentConfig.model,
43365
43509
  version,
@@ -43390,6 +43534,88 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
43390
43534
  fn();
43391
43535
  }
43392
43536
  }
43537
+ (async () => {
43538
+ if (!isResumed && !isFirstRun()) {
43539
+ try {
43540
+ const available = await isModelAvailable(config);
43541
+ if (!available && config.backendType === "ollama") {
43542
+ writeContent(() => {
43543
+ renderWarning(`Model "${config.model}" not available. Use /model to pick one.`);
43544
+ });
43545
+ }
43546
+ } catch {
43547
+ }
43548
+ }
43549
+ if (config.backendType === "ollama" && !config.model.startsWith("open-agents-")) {
43550
+ try {
43551
+ const expandResult = await ensureExpandedContext(config.model, config.backendUrl);
43552
+ if (expandResult.created) {
43553
+ config = { ...config, model: expandResult.model };
43554
+ currentConfig = { ...currentConfig, model: expandResult.model };
43555
+ statusBar.setModelName(expandResult.model);
43556
+ writeContent(() => renderInfo(`Created expanded context model: ${expandResult.model} (${expandResult.contextLabel}, ${expandResult.numCtx} tokens)`));
43557
+ } else if (expandResult.model !== config.model) {
43558
+ config = { ...config, model: expandResult.model };
43559
+ currentConfig = { ...currentConfig, model: expandResult.model };
43560
+ statusBar.setModelName(expandResult.model);
43561
+ writeContent(() => renderInfo(`Using expanded context model: ${expandResult.model} (${expandResult.contextLabel})`));
43562
+ }
43563
+ } catch {
43564
+ }
43565
+ }
43566
+ if (!isResumed) {
43567
+ try {
43568
+ const baseUrl = normalizeBaseUrl(config.backendUrl);
43569
+ const prov = detectProvider(config.backendUrl);
43570
+ const healthUrl = `${baseUrl}${prov.modelsPath}`;
43571
+ const headers = {};
43572
+ if (config.apiKey)
43573
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
43574
+ const resp = await fetch(healthUrl, { headers, signal: AbortSignal.timeout(1e4) });
43575
+ if (!resp.ok)
43576
+ throw new Error(`HTTP ${resp.status}`);
43577
+ } catch {
43578
+ const prov = detectProvider(config.backendUrl);
43579
+ writeContent(() => {
43580
+ renderWarning(`Cannot reach ${prov.label} at ${config.backendUrl}`);
43581
+ if (prov.id === "ollama") {
43582
+ renderInfo("Use /endpoint http://127.0.0.1:11434 to auto-install & start Ollama.");
43583
+ }
43584
+ renderInfo("Use /endpoint to configure a different backend.");
43585
+ });
43586
+ }
43587
+ }
43588
+ try {
43589
+ const oaDir = join50(repoRoot, ".oa");
43590
+ const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
43591
+ onInfo: (msg) => writeContent(() => renderInfo(msg)),
43592
+ onError: (msg) => writeContent(() => renderWarning(msg))
43593
+ });
43594
+ if (reconnected) {
43595
+ exposeGateway = reconnected;
43596
+ reconnected.on("stats", (stats) => {
43597
+ statusBar.setExposeStatus({
43598
+ status: stats.status,
43599
+ totalRequests: stats.totalRequests,
43600
+ activeConnections: stats.activeConnections,
43601
+ modelUsage: stats.modelUsage
43602
+ });
43603
+ });
43604
+ writeContent(() => {
43605
+ renderInfo(`Reconnected to existing expose tunnel: ${reconnected.tunnelUrl}`);
43606
+ });
43607
+ }
43608
+ } catch {
43609
+ }
43610
+ try {
43611
+ const isRemote = !currentConfig.backendUrl.includes("127.0.0.1") && !currentConfig.backendUrl.includes("localhost");
43612
+ if (isRemote) {
43613
+ statusBar.startRemoteMetricsPolling(currentConfig.backendUrl, currentConfig.apiKey);
43614
+ }
43615
+ } catch {
43616
+ }
43617
+ })().catch(() => {
43618
+ });
43393
43619
  function handleSudoRequest(_command) {
43394
43620
  if (sudoPromptPending)
43395
43621
  return;
@@ -44021,7 +44247,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
44021
44247
  kind = "custom";
44022
44248
  targetUrl = kindOrUrl.includes("://") ? kindOrUrl : `http://${kindOrUrl}`;
44023
44249
  }
44024
- exposeGateway = new ExposeGateway({ kind, targetUrl, authKey });
44250
+ exposeGateway = new ExposeGateway({ kind, targetUrl, authKey, stateDir: join50(repoRoot, ".oa") });
44025
44251
  exposeGateway.on("stats", (stats) => {
44026
44252
  statusBar.setExposeStatus({
44027
44253
  status: stats.status,
@@ -44208,8 +44434,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
44208
44434
  return true;
44209
44435
  },
44210
44436
  destroyProject() {
44211
- const oaPath = join49(repoRoot, OA_DIR);
44212
- if (existsSync38(oaPath)) {
44437
+ const oaPath = join50(repoRoot, OA_DIR);
44438
+ if (existsSync39(oaPath)) {
44213
44439
  try {
44214
44440
  rmSync2(oaPath, { recursive: true, force: true });
44215
44441
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -44540,13 +44766,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
44540
44766
  }
44541
44767
  }
44542
44768
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
44543
- const isImage = isImagePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
44544
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
44769
+ const isImage = isImagePath(cleanPath) && existsSync39(resolve28(repoRoot, cleanPath));
44770
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync39(resolve28(repoRoot, cleanPath));
44545
44771
  if (activeTask) {
44546
44772
  if (isImage) {
44547
44773
  try {
44548
44774
  const imgPath = resolve28(repoRoot, cleanPath);
44549
- const imgBuffer = readFileSync28(imgPath);
44775
+ const imgBuffer = readFileSync29(imgPath);
44550
44776
  const base64 = imgBuffer.toString("base64");
44551
44777
  const ext = extname9(cleanPath).toLowerCase();
44552
44778
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -44793,8 +45019,8 @@ NEW TASK: ${fullInput}`;
44793
45019
  try {
44794
45020
  const updateInfo = await checkForUpdate(version);
44795
45021
  if (updateInfo) {
44796
- const { exec: exec2 } = await import("node:child_process");
44797
- exec2(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
45022
+ const { exec: exec3 } = await import("node:child_process");
45023
+ exec3(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
44798
45024
  if (!err) {
44799
45025
  writeContent(() => renderInfo(`Updated to v${updateInfo.latestVersion} in background. Takes effect next session.`));
44800
45026
  }
@@ -44898,10 +45124,6 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
44898
45124
  showPrompt();
44899
45125
  }
44900
45126
  rl.on("close", () => {
44901
- if (exposeGateway?.isActive) {
44902
- exposeGateway.stop().catch(() => {
44903
- });
44904
- }
44905
45127
  if (peerMesh) {
44906
45128
  peerMesh.stop().catch(() => {
44907
45129
  });
@@ -45060,7 +45282,7 @@ import { glob } from "glob";
45060
45282
  import ignore from "ignore";
45061
45283
  import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
45062
45284
  import { createHash as createHash4 } from "node:crypto";
45063
- import { join as join50, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
45285
+ import { join as join51, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
45064
45286
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
45065
45287
  var init_codebase_indexer = __esm({
45066
45288
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -45104,7 +45326,7 @@ var init_codebase_indexer = __esm({
45104
45326
  const ig = ignore.default();
45105
45327
  if (this.config.respectGitignore) {
45106
45328
  try {
45107
- const gitignoreContent = await readFile16(join50(this.config.rootDir, ".gitignore"), "utf-8");
45329
+ const gitignoreContent = await readFile16(join51(this.config.rootDir, ".gitignore"), "utf-8");
45108
45330
  ig.add(gitignoreContent);
45109
45331
  } catch {
45110
45332
  }
@@ -45119,7 +45341,7 @@ var init_codebase_indexer = __esm({
45119
45341
  for (const relativePath of files) {
45120
45342
  if (ig.ignores(relativePath))
45121
45343
  continue;
45122
- const fullPath = join50(this.config.rootDir, relativePath);
45344
+ const fullPath = join51(this.config.rootDir, relativePath);
45123
45345
  try {
45124
45346
  const fileStat = await stat4(fullPath);
45125
45347
  if (fileStat.size > this.config.maxFileSize)
@@ -45165,7 +45387,7 @@ var init_codebase_indexer = __esm({
45165
45387
  if (!child) {
45166
45388
  child = {
45167
45389
  name: part,
45168
- path: join50(current.path, part),
45390
+ path: join51(current.path, part),
45169
45391
  type: "directory",
45170
45392
  children: []
45171
45393
  };
@@ -45248,13 +45470,13 @@ __export(index_repo_exports, {
45248
45470
  indexRepoCommand: () => indexRepoCommand
45249
45471
  });
45250
45472
  import { resolve as resolve29 } from "node:path";
45251
- import { existsSync as existsSync39, statSync as statSync11 } from "node:fs";
45473
+ import { existsSync as existsSync40, statSync as statSync11 } from "node:fs";
45252
45474
  import { cwd as cwd2 } from "node:process";
45253
45475
  async function indexRepoCommand(opts, _config) {
45254
45476
  const repoRoot = resolve29(opts.repoPath ?? cwd2());
45255
45477
  printHeader("Index Repository");
45256
45478
  printInfo(`Indexing: ${repoRoot}`);
45257
- if (!existsSync39(repoRoot)) {
45479
+ if (!existsSync40(repoRoot)) {
45258
45480
  printError(`Path does not exist: ${repoRoot}`);
45259
45481
  process.exit(1);
45260
45482
  }
@@ -45506,7 +45728,7 @@ var config_exports = {};
45506
45728
  __export(config_exports, {
45507
45729
  configCommand: () => configCommand
45508
45730
  });
45509
- import { join as join51, resolve as resolve30 } from "node:path";
45731
+ import { join as join52, resolve as resolve30 } from "node:path";
45510
45732
  import { homedir as homedir14 } from "node:os";
45511
45733
  import { cwd as cwd3 } from "node:process";
45512
45734
  function redactIfSensitive(key, value) {
@@ -45589,7 +45811,7 @@ function handleShow(opts, config) {
45589
45811
  }
45590
45812
  }
45591
45813
  printSection("Config File");
45592
- printInfo(`~/.open-agents/config.json (${join51(homedir14(), ".open-agents", "config.json")})`);
45814
+ printInfo(`~/.open-agents/config.json (${join52(homedir14(), ".open-agents", "config.json")})`);
45593
45815
  printSection("Priority Chain");
45594
45816
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
45595
45817
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -45628,7 +45850,7 @@ function handleSet(opts, _config) {
45628
45850
  const coerced = coerceForSettings(key, value);
45629
45851
  saveProjectSettings(repoRoot, { [key]: coerced });
45630
45852
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
45631
- printInfo(`Saved to ${join51(repoRoot, ".oa", "settings.json")}`);
45853
+ printInfo(`Saved to ${join52(repoRoot, ".oa", "settings.json")}`);
45632
45854
  printInfo("This override applies only when running in this workspace.");
45633
45855
  } catch (err) {
45634
45856
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -45886,8 +46108,8 @@ __export(eval_exports, {
45886
46108
  evalCommand: () => evalCommand
45887
46109
  });
45888
46110
  import { tmpdir as tmpdir7 } from "node:os";
45889
- import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "node:fs";
45890
- import { join as join52 } from "node:path";
46111
+ import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync17 } from "node:fs";
46112
+ import { join as join53 } from "node:path";
45891
46113
  async function evalCommand(opts, config) {
45892
46114
  const suiteName = opts.suite ?? "basic";
45893
46115
  const suite = SUITES[suiteName];
@@ -46012,9 +46234,9 @@ async function evalCommand(opts, config) {
46012
46234
  process.exit(failed > 0 ? 1 : 0);
46013
46235
  }
46014
46236
  function createTempEvalRepo() {
46015
- const dir = join52(tmpdir7(), `open-agents-eval-${Date.now()}`);
46237
+ const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
46016
46238
  mkdirSync18(dir, { recursive: true });
46017
- writeFileSync16(join52(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
46239
+ writeFileSync17(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
46018
46240
  return dir;
46019
46241
  }
46020
46242
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -46074,7 +46296,7 @@ init_updater();
46074
46296
  import { parseArgs as nodeParseArgs2 } from "node:util";
46075
46297
  import { createRequire as createRequire3 } from "node:module";
46076
46298
  import { fileURLToPath as fileURLToPath13 } from "node:url";
46077
- import { dirname as dirname18, join as join53 } from "node:path";
46299
+ import { dirname as dirname18, join as join54 } from "node:path";
46078
46300
 
46079
46301
  // packages/cli/dist/cli.js
46080
46302
  import { createInterface } from "node:readline";
@@ -46181,7 +46403,7 @@ init_output();
46181
46403
  function getVersion4() {
46182
46404
  try {
46183
46405
  const require2 = createRequire3(import.meta.url);
46184
- const pkgPath = join53(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
46406
+ const pkgPath = join54(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
46185
46407
  const pkg = require2(pkgPath);
46186
46408
  return pkg.version;
46187
46409
  } catch {