open-agents-ai 0.42.1 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1285,7 +1285,7 @@ ${stdinInput ?? ""}`);
1285
1285
  }
1286
1286
  runCommand(command, timeout, stdinInput) {
1287
1287
  const start = performance.now();
1288
- return new Promise((resolve26) => {
1288
+ return new Promise((resolve27) => {
1289
1289
  const child = spawn("bash", ["-c", command], {
1290
1290
  cwd: this.workingDir,
1291
1291
  env: {
@@ -1313,7 +1313,7 @@ ${stdinInput ?? ""}`);
1313
1313
  clearTimeout(timer);
1314
1314
  if (exitFlushTimer)
1315
1315
  clearTimeout(exitFlushTimer);
1316
- resolve26(result);
1316
+ resolve27(result);
1317
1317
  };
1318
1318
  const timer = setTimeout(() => {
1319
1319
  killed = true;
@@ -2317,7 +2317,7 @@ Meta: ${metaKeys.map((k) => `${k}="${meta[k]?.slice(0, 80)}"`).join(", ")}`);
2317
2317
  return null;
2318
2318
  }
2319
2319
  runProcess(cmd, args, timeoutMs) {
2320
- return new Promise((resolve26, reject) => {
2320
+ return new Promise((resolve27, reject) => {
2321
2321
  const proc = execFile3(cmd, args, {
2322
2322
  timeout: timeoutMs,
2323
2323
  maxBuffer: 10 * 1024 * 1024,
@@ -2327,7 +2327,7 @@ Meta: ${metaKeys.map((k) => `${k}="${meta[k]?.slice(0, 80)}"`).join(", ")}`);
2327
2327
  reject(new Error(`Process timeout after ${timeoutMs}ms`));
2328
2328
  return;
2329
2329
  }
2330
- resolve26({
2330
+ resolve27({
2331
2331
  stdout: String(stdout),
2332
2332
  stderr: String(stderr),
2333
2333
  exitCode: error ? error.code ?? 1 : 0
@@ -5361,7 +5361,7 @@ var init_custom_tool = __esm({
5361
5361
  }
5362
5362
  /** Execute a single shell command and return output */
5363
5363
  runCommand(command) {
5364
- return new Promise((resolve26) => {
5364
+ return new Promise((resolve27) => {
5365
5365
  const child = spawn3("bash", ["-c", command], {
5366
5366
  cwd: this.workingDir,
5367
5367
  env: { ...process.env, CI: "true", NO_COLOR: "1" },
@@ -5386,11 +5386,11 @@ var init_custom_tool = __esm({
5386
5386
  child.kill("SIGTERM");
5387
5387
  } catch {
5388
5388
  }
5389
- resolve26({ success: false, output: stdout, error: "Command timed out after 60s" });
5389
+ resolve27({ success: false, output: stdout, error: "Command timed out after 60s" });
5390
5390
  }, 6e4);
5391
5391
  child.on("close", (code) => {
5392
5392
  clearTimeout(timer);
5393
- resolve26({
5393
+ resolve27({
5394
5394
  success: code === 0,
5395
5395
  output: stdout + (stderr && code === 0 ? `
5396
5396
  STDERR:
@@ -5400,7 +5400,7 @@ ${stderr}` : ""),
5400
5400
  });
5401
5401
  child.on("error", (err) => {
5402
5402
  clearTimeout(timer);
5403
- resolve26({ success: false, output: stdout, error: err.message });
5403
+ resolve27({ success: false, output: stdout, error: err.message });
5404
5404
  });
5405
5405
  });
5406
5406
  }
@@ -6582,7 +6582,7 @@ import { writeFile as writeFile7, mkdtemp, rm, readdir as readdir2, stat } from
6582
6582
  import { join as join16 } from "node:path";
6583
6583
  import { tmpdir as tmpdir2 } from "node:os";
6584
6584
  function runProcess(cmd, args, options) {
6585
- return new Promise((resolve26) => {
6585
+ return new Promise((resolve27) => {
6586
6586
  const proc = spawn5(cmd, args, {
6587
6587
  cwd: options.cwd,
6588
6588
  timeout: options.timeout,
@@ -6612,7 +6612,7 @@ function runProcess(cmd, args, options) {
6612
6612
  }
6613
6613
  });
6614
6614
  proc.on("error", (err) => {
6615
- resolve26({
6615
+ resolve27({
6616
6616
  stdout,
6617
6617
  stderr: stderr || err.message,
6618
6618
  exitCode: 1,
@@ -6624,7 +6624,7 @@ function runProcess(cmd, args, options) {
6624
6624
  if (signal === "SIGTERM" || signal === "SIGKILL") {
6625
6625
  timedOut = true;
6626
6626
  }
6627
- resolve26({
6627
+ resolve27({
6628
6628
  stdout,
6629
6629
  stderr,
6630
6630
  exitCode: code ?? (timedOut ? 124 : 1),
@@ -8907,10 +8907,524 @@ var init_browser_action = __esm({
8907
8907
  }
8908
8908
  });
8909
8909
 
8910
+ // packages/execution/dist/tools/autoresearch.js
8911
+ import { execSync as execSync16, spawn as spawn8 } from "node:child_process";
8912
+ import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, appendFileSync, copyFileSync } from "node:fs";
8913
+ import { join as join22, resolve as resolve20, dirname as dirname9 } from "node:path";
8914
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
8915
+ function findAutoresearchScript(scriptName) {
8916
+ const thisDir = dirname9(fileURLToPath6(import.meta.url));
8917
+ const devPath = resolve20(thisDir, "../../scripts", scriptName);
8918
+ if (existsSync19(devPath))
8919
+ return devPath;
8920
+ const bundledPath = resolve20(thisDir, "../scripts", scriptName);
8921
+ if (existsSync19(bundledPath))
8922
+ return bundledPath;
8923
+ const sameDirPath = resolve20(thisDir, scriptName);
8924
+ if (existsSync19(sameDirPath))
8925
+ return sameDirPath;
8926
+ return null;
8927
+ }
8928
+ function parseRunLog(logContent) {
8929
+ const lines = logContent.split("\n");
8930
+ const result = {};
8931
+ for (const line of lines) {
8932
+ const match = line.match(/^(\w+):\s+([\d.]+)/);
8933
+ if (match) {
8934
+ result[match[1]] = parseFloat(match[2]);
8935
+ }
8936
+ }
8937
+ if (!result["val_bpb"])
8938
+ return null;
8939
+ return {
8940
+ val_bpb: result["val_bpb"],
8941
+ training_seconds: result["training_seconds"] ?? 0,
8942
+ total_seconds: result["total_seconds"] ?? 0,
8943
+ peak_vram_mb: result["peak_vram_mb"] ?? 0,
8944
+ mfu_percent: result["mfu_percent"] ?? 0,
8945
+ total_tokens_M: result["total_tokens_M"] ?? 0,
8946
+ num_steps: result["num_steps"] ?? 0,
8947
+ num_params_M: result["num_params_M"] ?? 0,
8948
+ depth: result["depth"] ?? 0
8949
+ };
8950
+ }
8951
+ var AutoresearchTool;
8952
+ var init_autoresearch = __esm({
8953
+ "packages/execution/dist/tools/autoresearch.js"() {
8954
+ "use strict";
8955
+ AutoresearchTool = class {
8956
+ repoRoot;
8957
+ name = "autoresearch";
8958
+ description = `Autonomous ML research experimentation (based on Karpathy's autoresearch).
8959
+
8960
+ Actions:
8961
+ - setup: Initialize workspace with training scripts, install deps, download data
8962
+ - run: Execute a single 5-minute training experiment, return parsed metrics
8963
+ - results: Show experiment history from results.tsv
8964
+ - status: Check workspace state (GPU, branch, last result)
8965
+ - keep: Record current experiment as keeper in results.tsv and commit
8966
+ - discard: Revert train.py to last committed state
8967
+
8968
+ The agent modifies train.py between experiments using file_edit. This tool handles infrastructure.
8969
+ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
8970
+ parameters = {
8971
+ type: "object",
8972
+ properties: {
8973
+ action: {
8974
+ type: "string",
8975
+ enum: ["setup", "run", "results", "status", "keep", "discard"],
8976
+ description: "Action to perform"
8977
+ },
8978
+ workspace: {
8979
+ type: "string",
8980
+ description: "Path to autoresearch workspace (default: .oa/autoresearch)"
8981
+ },
8982
+ tag: {
8983
+ type: "string",
8984
+ description: "Experiment tag for git branch (setup action, e.g. 'mar14')"
8985
+ },
8986
+ description: {
8987
+ type: "string",
8988
+ description: "Short description of the experiment (keep/discard actions)"
8989
+ },
8990
+ val_bpb: {
8991
+ type: "number",
8992
+ description: "val_bpb result to record (keep/discard actions \u2014 auto-detected from last run if omitted)"
8993
+ },
8994
+ memory_gb: {
8995
+ type: "number",
8996
+ description: "Peak memory in GB (keep/discard actions \u2014 auto-detected from last run if omitted)"
8997
+ },
8998
+ num_shards: {
8999
+ type: "number",
9000
+ description: "Number of data shards to download (setup action, default: 10)"
9001
+ },
9002
+ timeout_minutes: {
9003
+ type: "number",
9004
+ description: "Max wall-clock minutes for a run (default: 10, kills if exceeded)"
9005
+ }
9006
+ },
9007
+ required: ["action"]
9008
+ };
9009
+ constructor(repoRoot) {
9010
+ this.repoRoot = repoRoot;
9011
+ }
9012
+ async execute(args) {
9013
+ const start = Date.now();
9014
+ const action = String(args["action"] ?? "status");
9015
+ const workspacePath = String(args["workspace"] ?? join22(this.repoRoot, ".oa", "autoresearch"));
9016
+ try {
9017
+ switch (action) {
9018
+ case "setup":
9019
+ return await this.setup(workspacePath, args, start);
9020
+ case "run":
9021
+ return await this.run(workspacePath, args, start);
9022
+ case "results":
9023
+ return this.getResults(workspacePath, start);
9024
+ case "status":
9025
+ return this.getStatus(workspacePath, start);
9026
+ case "keep":
9027
+ return this.keepExperiment(workspacePath, args, start);
9028
+ case "discard":
9029
+ return this.discardExperiment(workspacePath, args, start);
9030
+ default:
9031
+ return { success: false, output: "", error: `Unknown action: ${action}. Use: setup, run, results, status, keep, discard`, durationMs: Date.now() - start };
9032
+ }
9033
+ } catch (err) {
9034
+ return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
9035
+ }
9036
+ }
9037
+ // ── Setup ──────────────────────────────────────────────────────────────
9038
+ async setup(workspace, args, start) {
9039
+ const output = [];
9040
+ try {
9041
+ execSync16("which uv", { encoding: "utf-8", timeout: 5e3 });
9042
+ output.push("uv: found");
9043
+ } catch {
9044
+ return { success: false, output: "", error: "uv not found. Install with: curl -LsSf https://astral.sh/uv/install.sh | sh", durationMs: Date.now() - start };
9045
+ }
9046
+ try {
9047
+ const gpuInfo = execSync16("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null || echo 'no GPU'", { encoding: "utf-8", timeout: 1e4 }).trim();
9048
+ output.push(`GPU: ${gpuInfo}`);
9049
+ } catch {
9050
+ output.push("GPU: detection failed (nvidia-smi not available)");
9051
+ }
9052
+ mkdirSync5(workspace, { recursive: true });
9053
+ const prepareScript = findAutoresearchScript("autoresearch-prepare.py");
9054
+ const trainScript = findAutoresearchScript("autoresearch-train.py");
9055
+ if (prepareScript) {
9056
+ copyFileSync(prepareScript, join22(workspace, "prepare.py"));
9057
+ output.push("Copied prepare.py template");
9058
+ } else {
9059
+ return { success: false, output: output.join("\n"), error: "autoresearch-prepare.py template not found in distribution", durationMs: Date.now() - start };
9060
+ }
9061
+ if (trainScript) {
9062
+ copyFileSync(trainScript, join22(workspace, "train.py"));
9063
+ output.push("Copied train.py template");
9064
+ } else {
9065
+ return { success: false, output: output.join("\n"), error: "autoresearch-train.py template not found in distribution", durationMs: Date.now() - start };
9066
+ }
9067
+ const pyprojectContent = `[project]
9068
+ name = "autoresearch"
9069
+ version = "0.1.0"
9070
+ description = "Autonomous pretraining research"
9071
+ requires-python = ">=3.10"
9072
+ dependencies = [
9073
+ "kernels>=0.11.7",
9074
+ "matplotlib>=3.10.8",
9075
+ "numpy>=2.2.6",
9076
+ "pandas>=2.3.3",
9077
+ "pyarrow>=21.0.0",
9078
+ "requests>=2.32.0",
9079
+ "rustbpe>=0.1.0",
9080
+ "tiktoken>=0.11.0",
9081
+ "torch==2.9.1",
9082
+ ]
9083
+
9084
+ [tool.uv.sources]
9085
+ torch = [
9086
+ { index = "pytorch-cu128" },
9087
+ ]
9088
+
9089
+ [[tool.uv.index]]
9090
+ name = "pytorch-cu128"
9091
+ url = "https://download.pytorch.org/whl/cu128"
9092
+ explicit = true
9093
+ `;
9094
+ writeFileSync5(join22(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
9095
+ output.push("Created pyproject.toml");
9096
+ try {
9097
+ execSync16("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
9098
+ output.push("Git: already initialized");
9099
+ } catch {
9100
+ execSync16("git init && git add -A && git commit -m 'autoresearch: initial setup'", {
9101
+ cwd: workspace,
9102
+ encoding: "utf-8",
9103
+ timeout: 1e4
9104
+ });
9105
+ output.push("Git: initialized with initial commit");
9106
+ }
9107
+ const tag = String(args["tag"] ?? (/* @__PURE__ */ new Date()).toISOString().slice(5, 10).replace("-", ""));
9108
+ const branchName = `autoresearch/${tag}`;
9109
+ try {
9110
+ execSync16(`git checkout -b ${branchName}`, { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
9111
+ output.push(`Branch: created ${branchName}`);
9112
+ } catch {
9113
+ output.push(`Branch: ${branchName} may already exist, staying on current branch`);
9114
+ }
9115
+ output.push("Installing dependencies with uv sync (this may take a while)...");
9116
+ try {
9117
+ const uvOut = execSync16("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
9118
+ output.push(`uv sync: ${uvOut.trim().split("\n").slice(-3).join(" | ")}`);
9119
+ } catch (err) {
9120
+ const e = err;
9121
+ output.push(`uv sync warning: ${(e.stderr ?? e.stdout ?? "failed").slice(0, 500)}`);
9122
+ }
9123
+ const numShards = Number(args["num_shards"] ?? 10);
9124
+ output.push(`Preparing data (${numShards} shards)...`);
9125
+ try {
9126
+ const prepOut = execSync16(`uv run prepare.py --num-shards ${numShards} 2>&1`, {
9127
+ cwd: workspace,
9128
+ encoding: "utf-8",
9129
+ timeout: 6e5
9130
+ });
9131
+ output.push(`Data prep: ${prepOut.trim().split("\n").slice(-3).join(" | ")}`);
9132
+ } catch (err) {
9133
+ const e = err;
9134
+ output.push(`Data prep warning: ${(e.stderr ?? e.stdout ?? "failed").slice(0, 500)}`);
9135
+ }
9136
+ const tsvPath = join22(workspace, "results.tsv");
9137
+ if (!existsSync19(tsvPath)) {
9138
+ writeFileSync5(tsvPath, "commit val_bpb memory_gb status description\n", "utf-8");
9139
+ output.push("Created results.tsv");
9140
+ }
9141
+ return {
9142
+ success: true,
9143
+ output: `Autoresearch workspace ready at ${workspace}
9144
+
9145
+ ${output.join("\n")}
9146
+
9147
+ Next steps:
9148
+ 1. Run baseline: autoresearch(action="run") \u2014 establishes starting val_bpb
9149
+ 2. Record baseline: autoresearch(action="keep", description="baseline")
9150
+ 3. Modify train.py with file_edit, then run again
9151
+ 4. Keep or discard based on val_bpb improvement
9152
+ 5. Repeat \u2014 iteration beats perfection!`,
9153
+ durationMs: Date.now() - start
9154
+ };
9155
+ }
9156
+ // ── Run experiment ─────────────────────────────────────────────────────
9157
+ async run(workspace, args, start) {
9158
+ if (!existsSync19(join22(workspace, "train.py"))) {
9159
+ return { success: false, output: "", error: `No train.py found in ${workspace}. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9160
+ }
9161
+ const timeoutMin = Number(args["timeout_minutes"] ?? 10);
9162
+ const timeoutMs = timeoutMin * 60 * 1e3;
9163
+ const logPath = join22(workspace, "run.log");
9164
+ return new Promise((resolveResult) => {
9165
+ const proc = spawn8("uv", ["run", "train.py"], {
9166
+ cwd: workspace,
9167
+ timeout: timeoutMs,
9168
+ stdio: ["pipe", "pipe", "pipe"],
9169
+ env: { ...process.env, PYTORCH_ALLOC_CONF: "expandable_segments:True" }
9170
+ });
9171
+ let stdout = "";
9172
+ let stderr = "";
9173
+ let timedOut = false;
9174
+ proc.stdout.on("data", (d) => {
9175
+ stdout += d.toString();
9176
+ if (stdout.length > 5e5) {
9177
+ stdout = stdout.slice(-2e5);
9178
+ }
9179
+ });
9180
+ proc.stderr.on("data", (d) => {
9181
+ stderr += d.toString();
9182
+ if (stderr.length > 1e5) {
9183
+ stderr = stderr.slice(-5e4);
9184
+ }
9185
+ });
9186
+ const timer = setTimeout(() => {
9187
+ timedOut = true;
9188
+ proc.kill("SIGKILL");
9189
+ }, timeoutMs);
9190
+ proc.on("close", (code) => {
9191
+ clearTimeout(timer);
9192
+ const fullLog = stdout + "\n" + stderr;
9193
+ try {
9194
+ writeFileSync5(logPath, fullLog, "utf-8");
9195
+ } catch {
9196
+ }
9197
+ if (timedOut) {
9198
+ resolveResult({
9199
+ success: false,
9200
+ output: `Experiment timed out after ${timeoutMin} minutes.
9201
+ Last output:
9202
+ ${fullLog.slice(-2e3)}`,
9203
+ error: "Training exceeded timeout \u2014 treat as failed experiment",
9204
+ durationMs: Date.now() - start
9205
+ });
9206
+ return;
9207
+ }
9208
+ if (code !== 0) {
9209
+ const tail = fullLog.split("\n").slice(-50).join("\n");
9210
+ resolveResult({
9211
+ success: false,
9212
+ output: `Experiment crashed (exit code ${code}).
9213
+
9214
+ Last 50 lines:
9215
+ ${tail}`,
9216
+ error: "Training crashed \u2014 check the error above, fix train.py, and re-run",
9217
+ durationMs: Date.now() - start
9218
+ });
9219
+ return;
9220
+ }
9221
+ const result = parseRunLog(fullLog);
9222
+ if (!result) {
9223
+ resolveResult({
9224
+ success: false,
9225
+ output: `Experiment completed but no val_bpb found in output.
9226
+ Log tail:
9227
+ ${fullLog.slice(-2e3)}`,
9228
+ error: "Could not parse experiment results",
9229
+ durationMs: Date.now() - start
9230
+ });
9231
+ return;
9232
+ }
9233
+ try {
9234
+ writeFileSync5(join22(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
9235
+ } catch {
9236
+ }
9237
+ const memGB = (result.peak_vram_mb / 1024).toFixed(1);
9238
+ const output = [
9239
+ `Experiment complete!`,
9240
+ ``,
9241
+ `val_bpb: ${result.val_bpb.toFixed(6)}`,
9242
+ `training_seconds: ${result.training_seconds.toFixed(1)}`,
9243
+ `total_seconds: ${result.total_seconds.toFixed(1)}`,
9244
+ `peak_vram_mb: ${result.peak_vram_mb.toFixed(1)} (${memGB} GB)`,
9245
+ `mfu_percent: ${result.mfu_percent.toFixed(2)}`,
9246
+ `total_tokens_M: ${result.total_tokens_M.toFixed(1)}`,
9247
+ `num_steps: ${result.num_steps}`,
9248
+ `num_params_M: ${result.num_params_M.toFixed(1)}`,
9249
+ `depth: ${result.depth}`,
9250
+ ``,
9251
+ `Next: Compare val_bpb to previous best.`,
9252
+ ` If improved: autoresearch(action="keep", description="what you changed")`,
9253
+ ` If worse: autoresearch(action="discard", description="what you tried")`
9254
+ ].join("\n");
9255
+ resolveResult({ success: true, output, durationMs: Date.now() - start });
9256
+ });
9257
+ proc.on("error", (err) => {
9258
+ clearTimeout(timer);
9259
+ resolveResult({
9260
+ success: false,
9261
+ output: "",
9262
+ error: `Failed to start training: ${err.message}. Is uv installed and GPU available?`,
9263
+ durationMs: Date.now() - start
9264
+ });
9265
+ });
9266
+ });
9267
+ }
9268
+ // ── Results ────────────────────────────────────────────────────────────
9269
+ getResults(workspace, start) {
9270
+ const tsvPath = join22(workspace, "results.tsv");
9271
+ if (!existsSync19(tsvPath)) {
9272
+ return { success: false, output: "", error: `No results.tsv found. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9273
+ }
9274
+ const content = readFileSync14(tsvPath, "utf-8");
9275
+ const lines = content.trim().split("\n");
9276
+ if (lines.length <= 1) {
9277
+ return { success: true, output: 'No experiments recorded yet. Run autoresearch(action="run") to start.', durationMs: Date.now() - start };
9278
+ }
9279
+ const experiments = lines.slice(1).map((line) => {
9280
+ const [commit, bpb, mem, status, desc] = line.split(" ");
9281
+ return { commit, val_bpb: parseFloat(bpb ?? "0"), memory_gb: parseFloat(mem ?? "0"), status, description: desc };
9282
+ });
9283
+ const kept = experiments.filter((e) => e.status === "keep");
9284
+ const best = kept.reduce((a, b) => a.val_bpb < b.val_bpb && a.val_bpb > 0 ? a : b, kept[0]);
9285
+ const summary = [
9286
+ `Experiments: ${experiments.length} total, ${kept.length} kept, ${experiments.filter((e) => e.status === "discard").length} discarded, ${experiments.filter((e) => e.status === "crash").length} crashed`,
9287
+ `Best val_bpb: ${best?.val_bpb?.toFixed(6) ?? "N/A"} (${best?.description ?? "N/A"})`,
9288
+ ``,
9289
+ `Full history:`,
9290
+ content
9291
+ ].join("\n");
9292
+ return { success: true, output: summary, durationMs: Date.now() - start };
9293
+ }
9294
+ // ── Status ─────────────────────────────────────────────────────────────
9295
+ getStatus(workspace, start) {
9296
+ const output = [];
9297
+ if (!existsSync19(join22(workspace, "train.py"))) {
9298
+ return {
9299
+ success: true,
9300
+ output: `Autoresearch workspace not initialized at ${workspace}.
9301
+ Run autoresearch(action="setup") to begin.`,
9302
+ durationMs: Date.now() - start
9303
+ };
9304
+ }
9305
+ output.push(`Workspace: ${workspace}`);
9306
+ try {
9307
+ const branch = execSync16("git branch --show-current", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
9308
+ output.push(`Branch: ${branch}`);
9309
+ const lastCommit = execSync16("git log --oneline -1", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
9310
+ output.push(`Last commit: ${lastCommit}`);
9311
+ } catch {
9312
+ output.push("Git: not initialized");
9313
+ }
9314
+ try {
9315
+ const gpuInfo = execSync16("nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader 2>/dev/null", { encoding: "utf-8", timeout: 1e4 }).trim();
9316
+ output.push(`GPU: ${gpuInfo}`);
9317
+ } catch {
9318
+ output.push("GPU: not detected");
9319
+ }
9320
+ const lastResultPath = join22(workspace, ".last-result.json");
9321
+ if (existsSync19(lastResultPath)) {
9322
+ try {
9323
+ const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9324
+ output.push(`Last experiment: val_bpb=${last.val_bpb.toFixed(6)}, ${(last.peak_vram_mb / 1024).toFixed(1)}GB VRAM, ${last.num_params_M.toFixed(1)}M params`);
9325
+ } catch {
9326
+ }
9327
+ }
9328
+ const tsvPath = join22(workspace, "results.tsv");
9329
+ if (existsSync19(tsvPath)) {
9330
+ const lines = readFileSync14(tsvPath, "utf-8").trim().split("\n");
9331
+ output.push(`Experiments recorded: ${lines.length - 1}`);
9332
+ }
9333
+ const cacheDir = join22(process.env["HOME"] ?? "~", ".cache", "autoresearch");
9334
+ output.push(`Data cache: ${existsSync19(cacheDir) ? "present" : "not found"} (${cacheDir})`);
9335
+ return { success: true, output: output.join("\n"), durationMs: Date.now() - start };
9336
+ }
9337
+ // ── Keep / Discard ─────────────────────────────────────────────────────
9338
+ keepExperiment(workspace, args, start) {
9339
+ const desc = String(args["description"] ?? "experiment");
9340
+ const tsvPath = join22(workspace, "results.tsv");
9341
+ const lastResultPath = join22(workspace, ".last-result.json");
9342
+ let valBpb = args["val_bpb"];
9343
+ let memGb = args["memory_gb"];
9344
+ if ((valBpb === void 0 || memGb === void 0) && existsSync19(lastResultPath)) {
9345
+ try {
9346
+ const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9347
+ if (valBpb === void 0)
9348
+ valBpb = last.val_bpb;
9349
+ if (memGb === void 0)
9350
+ memGb = parseFloat((last.peak_vram_mb / 1024).toFixed(1));
9351
+ } catch {
9352
+ }
9353
+ }
9354
+ valBpb = valBpb ?? 0;
9355
+ memGb = memGb ?? 0;
9356
+ let commitHash = "0000000";
9357
+ try {
9358
+ execSync16("git add train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
9359
+ execSync16(`git commit -m "autoresearch: ${desc}"`, { cwd: workspace, encoding: "utf-8", timeout: 1e4 });
9360
+ commitHash = execSync16("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
9361
+ } catch {
9362
+ try {
9363
+ commitHash = execSync16("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
9364
+ } catch {
9365
+ }
9366
+ }
9367
+ const row = `${commitHash} ${valBpb.toFixed(6)} ${memGb.toFixed(1)} keep ${desc}
9368
+ `;
9369
+ appendFileSync(tsvPath, row, "utf-8");
9370
+ return {
9371
+ success: true,
9372
+ output: `Kept: ${commitHash} | val_bpb=${valBpb.toFixed(6)} | ${memGb.toFixed(1)}GB | ${desc}
9373
+ Branch advanced. Ready for next experiment.`,
9374
+ durationMs: Date.now() - start
9375
+ };
9376
+ }
9377
+ discardExperiment(workspace, args, start) {
9378
+ const desc = String(args["description"] ?? "experiment");
9379
+ const tsvPath = join22(workspace, "results.tsv");
9380
+ const lastResultPath = join22(workspace, ".last-result.json");
9381
+ let valBpb = args["val_bpb"];
9382
+ let memGb = args["memory_gb"];
9383
+ if ((valBpb === void 0 || memGb === void 0) && existsSync19(lastResultPath)) {
9384
+ try {
9385
+ const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9386
+ if (valBpb === void 0)
9387
+ valBpb = last.val_bpb;
9388
+ if (memGb === void 0)
9389
+ memGb = parseFloat((last.peak_vram_mb / 1024).toFixed(1));
9390
+ } catch {
9391
+ }
9392
+ }
9393
+ valBpb = valBpb ?? 0;
9394
+ memGb = memGb ?? 0;
9395
+ let commitHash = "0000000";
9396
+ try {
9397
+ commitHash = execSync16("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
9398
+ } catch {
9399
+ }
9400
+ const row = `${commitHash} ${valBpb.toFixed(6)} ${memGb.toFixed(1)} discard ${desc}
9401
+ `;
9402
+ appendFileSync(tsvPath, row, "utf-8");
9403
+ try {
9404
+ execSync16("git checkout -- train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
9405
+ } catch {
9406
+ return {
9407
+ success: false,
9408
+ output: `Recorded discard but failed to revert train.py`,
9409
+ error: "git checkout -- train.py failed",
9410
+ durationMs: Date.now() - start
9411
+ };
9412
+ }
9413
+ return {
9414
+ success: true,
9415
+ output: `Discarded: val_bpb=${valBpb.toFixed(6)} | ${memGb.toFixed(1)}GB | ${desc}
9416
+ train.py reverted to last kept state. Ready for next experiment.`,
9417
+ durationMs: Date.now() - start
9418
+ };
9419
+ }
9420
+ };
9421
+ }
9422
+ });
9423
+
8910
9424
  // packages/execution/dist/tools/scheduler.js
8911
- import { execSync as execSync16, exec as execCb } from "node:child_process";
9425
+ import { execSync as execSync17, exec as execCb } from "node:child_process";
8912
9426
  import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir4 } from "node:fs/promises";
8913
- import { resolve as resolve20, join as join22 } from "node:path";
9427
+ import { resolve as resolve21, join as join23 } from "node:path";
8914
9428
  import { randomBytes as randomBytes2 } from "node:crypto";
8915
9429
  function isValidCron(expr) {
8916
9430
  const parts = expr.trim().split(/\s+/);
@@ -8970,19 +9484,19 @@ function describeCron(expr) {
8970
9484
  }
8971
9485
  function getCurrentCrontab() {
8972
9486
  try {
8973
- return execSync16("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
9487
+ return execSync17("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
8974
9488
  } catch {
8975
9489
  return [];
8976
9490
  }
8977
9491
  }
8978
9492
  function writeCrontab(lines) {
8979
9493
  const content = lines.join("\n") + "\n";
8980
- execSync16(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
9494
+ execSync17(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
8981
9495
  }
8982
9496
  function findOaBinary() {
8983
9497
  for (const cmd of ["oa", "open-agents"]) {
8984
9498
  try {
8985
- const path = execSync16(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
9499
+ const path = execSync17(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
8986
9500
  if (path)
8987
9501
  return path;
8988
9502
  } catch {
@@ -8993,8 +9507,8 @@ function findOaBinary() {
8993
9507
  function installCronJob(task, workingDir) {
8994
9508
  const lines = getCurrentCrontab();
8995
9509
  const oaBin = findOaBinary();
8996
- const logDir = resolve20(workingDir, ".oa", "scheduled", "logs");
8997
- const logFile = join22(logDir, `${task.id}.log`);
9510
+ const logDir = resolve21(workingDir, ".oa", "scheduled", "logs");
9511
+ const logFile = join23(logDir, `${task.id}.log`);
8998
9512
  const cronLine = `${task.schedule} cd ${JSON.stringify(workingDir)} && ${oaBin} ${JSON.stringify(task.task)} >> ${JSON.stringify(logFile)} 2>&1 ${CRON_MARKER}${task.id}`;
8999
9513
  const filtered = lines.filter((l) => !l.includes(`${CRON_MARKER}${task.id}`));
9000
9514
  filtered.push(cronLine);
@@ -9014,7 +9528,7 @@ function listCronJobs() {
9014
9528
  });
9015
9529
  }
9016
9530
  async function loadStore(workingDir) {
9017
- const storePath = resolve20(workingDir, ".oa", "scheduled", "tasks.json");
9531
+ const storePath = resolve21(workingDir, ".oa", "scheduled", "tasks.json");
9018
9532
  try {
9019
9533
  const raw = await readFile9(storePath, "utf-8");
9020
9534
  return JSON.parse(raw);
@@ -9023,11 +9537,11 @@ async function loadStore(workingDir) {
9023
9537
  }
9024
9538
  }
9025
9539
  async function saveStore(workingDir, store) {
9026
- const dir = resolve20(workingDir, ".oa", "scheduled");
9540
+ const dir = resolve21(workingDir, ".oa", "scheduled");
9027
9541
  await mkdir4(dir, { recursive: true });
9028
- await mkdir4(join22(dir, "logs"), { recursive: true });
9542
+ await mkdir4(join23(dir, "logs"), { recursive: true });
9029
9543
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
9030
- await writeFile8(join22(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
9544
+ await writeFile8(join23(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
9031
9545
  }
9032
9546
  var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
9033
9547
  var init_scheduler = __esm({
@@ -9245,7 +9759,7 @@ var init_scheduler = __esm({
9245
9759
  const id = String(args["id"] ?? "");
9246
9760
  if (!id)
9247
9761
  return { success: false, output: "", error: "id is required for logs action", durationMs: performance.now() - start };
9248
- const logFile = resolve20(this.workingDir, ".oa", "scheduled", "logs", `${id}.log`);
9762
+ const logFile = resolve21(this.workingDir, ".oa", "scheduled", "logs", `${id}.log`);
9249
9763
  try {
9250
9764
  const raw = await readFile9(logFile, "utf-8");
9251
9765
  const truncated = raw.length > 1e4 ? "...(truncated)\n" + raw.slice(-1e4) : raw;
@@ -9261,7 +9775,7 @@ ${truncated}`, durationMs: performance.now() - start };
9261
9775
 
9262
9776
  // packages/execution/dist/tools/reminder.js
9263
9777
  import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir5 } from "node:fs/promises";
9264
- import { resolve as resolve21, join as join23 } from "node:path";
9778
+ import { resolve as resolve22, join as join24 } from "node:path";
9265
9779
  import { randomBytes as randomBytes3 } from "node:crypto";
9266
9780
  function parseDueTime(due) {
9267
9781
  const lower = due.toLowerCase().trim();
@@ -9311,9 +9825,9 @@ function parseDueTime(due) {
9311
9825
  return null;
9312
9826
  }
9313
9827
  async function getStorePath(workingDir) {
9314
- const dir = resolve21(workingDir, ".oa", "scheduled");
9828
+ const dir = resolve22(workingDir, ".oa", "scheduled");
9315
9829
  await mkdir5(dir, { recursive: true });
9316
- return join23(dir, STORE_FILE);
9830
+ return join24(dir, STORE_FILE);
9317
9831
  }
9318
9832
  async function loadReminderStore(workingDir) {
9319
9833
  const storePath = await getStorePath(workingDir);
@@ -9574,10 +10088,10 @@ var init_reminder = __esm({
9574
10088
 
9575
10089
  // packages/execution/dist/tools/agenda.js
9576
10090
  import { readFile as readFile11, writeFile as writeFile10, mkdir as mkdir6 } from "node:fs/promises";
9577
- import { resolve as resolve22, join as join24 } from "node:path";
10091
+ import { resolve as resolve23, join as join25 } from "node:path";
9578
10092
  import { randomBytes as randomBytes4 } from "node:crypto";
9579
10093
  async function loadAttentionStore(workingDir) {
9580
- const storePath = resolve22(workingDir, ".oa", "scheduled", "attention.json");
10094
+ const storePath = resolve23(workingDir, ".oa", "scheduled", "attention.json");
9581
10095
  try {
9582
10096
  const raw = await readFile11(storePath, "utf-8");
9583
10097
  return JSON.parse(raw);
@@ -9586,10 +10100,10 @@ async function loadAttentionStore(workingDir) {
9586
10100
  }
9587
10101
  }
9588
10102
  async function saveAttentionStore(workingDir, store) {
9589
- const dir = resolve22(workingDir, ".oa", "scheduled");
10103
+ const dir = resolve23(workingDir, ".oa", "scheduled");
9590
10104
  await mkdir6(dir, { recursive: true });
9591
10105
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
9592
- await writeFile10(join24(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
10106
+ await writeFile10(join25(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
9593
10107
  }
9594
10108
  async function getActiveAttentionItems(workingDir) {
9595
10109
  const store = await loadAttentionStore(workingDir);
@@ -9884,7 +10398,7 @@ ${sections.join("\n")}`,
9884
10398
  }
9885
10399
  async loadScheduleStore() {
9886
10400
  try {
9887
- const storePath = resolve22(this.workingDir, ".oa", "scheduled", "tasks.json");
10401
+ const storePath = resolve23(this.workingDir, ".oa", "scheduled", "tasks.json");
9888
10402
  const raw = await readFile11(storePath, "utf-8");
9889
10403
  const store = JSON.parse(raw);
9890
10404
  return store.tasks ?? [];
@@ -10012,6 +10526,7 @@ var init_dist2 = __esm({
10012
10526
  init_pdf_to_text();
10013
10527
  init_ocr_image_advanced();
10014
10528
  init_browser_action();
10529
+ init_autoresearch();
10015
10530
  init_scheduler();
10016
10531
  init_reminder();
10017
10532
  init_agenda();
@@ -11147,7 +11662,7 @@ var init_code_retriever = __esm({
11147
11662
  import { execFile as execFile5 } from "node:child_process";
11148
11663
  import { promisify as promisify4 } from "node:util";
11149
11664
  import { readFile as readFile12, readdir as readdir3, stat as stat3 } from "node:fs/promises";
11150
- import { join as join25, extname as extname7 } from "node:path";
11665
+ import { join as join26, extname as extname7 } from "node:path";
11151
11666
  async function searchByPath(pathPattern, options) {
11152
11667
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
11153
11668
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -11289,7 +11804,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
11289
11804
  continue;
11290
11805
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
11291
11806
  continue;
11292
- const absPath = join25(dir, entry.name);
11807
+ const absPath = join26(dir, entry.name);
11293
11808
  if (entry.isDirectory()) {
11294
11809
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
11295
11810
  } else if (entry.isFile()) {
@@ -11596,7 +12111,7 @@ var init_graphExpand = __esm({
11596
12111
 
11597
12112
  // packages/retrieval/dist/snippetPacker.js
11598
12113
  import { readFile as readFile13 } from "node:fs/promises";
11599
- import { join as join26 } from "node:path";
12114
+ import { join as join27 } from "node:path";
11600
12115
  async function packSnippets(requests, opts = {}) {
11601
12116
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
11602
12117
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -11622,7 +12137,7 @@ async function packSnippets(requests, opts = {}) {
11622
12137
  return { packed, dropped, totalTokens };
11623
12138
  }
11624
12139
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
11625
- const absPath = req.filePath.startsWith("/") ? req.filePath : join26(repoRoot, req.filePath);
12140
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join27(repoRoot, req.filePath);
11626
12141
  let content;
11627
12142
  try {
11628
12143
  content = await readFile13(absPath, "utf-8");
@@ -13358,8 +13873,8 @@ Rules:
13358
13873
  async waitIfPaused() {
13359
13874
  if (!this._paused)
13360
13875
  return true;
13361
- await new Promise((resolve26) => {
13362
- this._pauseResolve = resolve26;
13876
+ await new Promise((resolve27) => {
13877
+ this._pauseResolve = resolve27;
13363
13878
  });
13364
13879
  return !this.aborted;
13365
13880
  }
@@ -13939,14 +14454,14 @@ ${result.output}`;
13939
14454
  waitForSudoPassword(timeoutMs = 12e4) {
13940
14455
  if (this._sudoPassword)
13941
14456
  return Promise.resolve(this._sudoPassword);
13942
- return new Promise((resolve26) => {
14457
+ return new Promise((resolve27) => {
13943
14458
  const timer = setTimeout(() => {
13944
14459
  this._sudoResolve = null;
13945
- resolve26(null);
14460
+ resolve27(null);
13946
14461
  }, timeoutMs);
13947
14462
  this._sudoResolve = (pw) => {
13948
14463
  clearTimeout(timer);
13949
- resolve26(pw);
14464
+ resolve27(pw);
13950
14465
  };
13951
14466
  });
13952
14467
  }
@@ -14068,10 +14583,10 @@ ${marker}` : marker);
14068
14583
  if (!this._workingDirectory)
14069
14584
  return;
14070
14585
  try {
14071
- const { mkdirSync: mkdirSync14, writeFileSync: writeFileSync13 } = __require("node:fs");
14072
- const { join: join43 } = __require("node:path");
14073
- const sessionDir = join43(this._workingDirectory, ".oa", "session", this._sessionId);
14074
- mkdirSync14(sessionDir, { recursive: true });
14586
+ const { mkdirSync: mkdirSync15, writeFileSync: writeFileSync14 } = __require("node:fs");
14587
+ const { join: join44 } = __require("node:path");
14588
+ const sessionDir = join44(this._workingDirectory, ".oa", "session", this._sessionId);
14589
+ mkdirSync15(sessionDir, { recursive: true });
14075
14590
  const checkpoint = {
14076
14591
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
14077
14592
  sessionId: this._sessionId,
@@ -14083,7 +14598,7 @@ ${marker}` : marker);
14083
14598
  memexEntryCount: this._memexArchive.size,
14084
14599
  fileRegistrySize: this._fileRegistry.size
14085
14600
  };
14086
- writeFileSync13(join43(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
14601
+ writeFileSync14(join44(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
14087
14602
  } catch {
14088
14603
  }
14089
14604
  }
@@ -15621,11 +16136,11 @@ var init_dist5 = __esm({
15621
16136
  });
15622
16137
 
15623
16138
  // packages/cli/dist/tui/listen.js
15624
- import { spawn as spawn8, execSync as execSync17 } from "node:child_process";
15625
- import { existsSync as existsSync19, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
15626
- import { join as join27, dirname as dirname9 } from "node:path";
16139
+ import { spawn as spawn9, execSync as execSync18 } from "node:child_process";
16140
+ import { existsSync as existsSync20, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
16141
+ import { join as join28, dirname as dirname10 } from "node:path";
15627
16142
  import { homedir as homedir8 } from "node:os";
15628
- import { fileURLToPath as fileURLToPath6 } from "node:url";
16143
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
15629
16144
  import { EventEmitter } from "node:events";
15630
16145
  import { createInterface as createInterface2 } from "node:readline";
15631
16146
  function isAudioPath(path) {
@@ -15643,7 +16158,7 @@ function findMicCaptureCommand() {
15643
16158
  const platform4 = process.platform;
15644
16159
  if (platform4 === "linux") {
15645
16160
  try {
15646
- execSync17("which arecord", { stdio: "pipe" });
16161
+ execSync18("which arecord", { stdio: "pipe" });
15647
16162
  return {
15648
16163
  cmd: "arecord",
15649
16164
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -15653,7 +16168,7 @@ function findMicCaptureCommand() {
15653
16168
  }
15654
16169
  if (platform4 === "darwin") {
15655
16170
  try {
15656
- execSync17("which sox", { stdio: "pipe" });
16171
+ execSync18("which sox", { stdio: "pipe" });
15657
16172
  return {
15658
16173
  cmd: "sox",
15659
16174
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -15662,7 +16177,7 @@ function findMicCaptureCommand() {
15662
16177
  }
15663
16178
  }
15664
16179
  try {
15665
- execSync17("which ffmpeg", { stdio: "pipe" });
16180
+ execSync18("which ffmpeg", { stdio: "pipe" });
15666
16181
  if (platform4 === "linux") {
15667
16182
  return {
15668
16183
  cmd: "ffmpeg",
@@ -15707,41 +16222,41 @@ function findMicCaptureCommand() {
15707
16222
  return null;
15708
16223
  }
15709
16224
  function findLiveWhisperScript() {
15710
- const thisDir = dirname9(fileURLToPath6(import.meta.url));
16225
+ const thisDir = dirname10(fileURLToPath7(import.meta.url));
15711
16226
  const candidates = [
15712
- join27(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
15713
- join27(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
15714
- join27(thisDir, "../../execution/scripts/live-whisper.py"),
16227
+ join28(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
16228
+ join28(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
16229
+ join28(thisDir, "../../execution/scripts/live-whisper.py"),
15715
16230
  // npm install layout — scripts bundled alongside dist
15716
- join27(thisDir, "../scripts/live-whisper.py"),
15717
- join27(thisDir, "../../scripts/live-whisper.py")
16231
+ join28(thisDir, "../scripts/live-whisper.py"),
16232
+ join28(thisDir, "../../scripts/live-whisper.py")
15718
16233
  ];
15719
16234
  for (const p of candidates) {
15720
- if (existsSync19(p))
16235
+ if (existsSync20(p))
15721
16236
  return p;
15722
16237
  }
15723
16238
  try {
15724
- const globalRoot = execSync17("npm root -g", {
16239
+ const globalRoot = execSync18("npm root -g", {
15725
16240
  encoding: "utf-8",
15726
16241
  timeout: 5e3,
15727
16242
  stdio: ["pipe", "pipe", "pipe"]
15728
16243
  }).trim();
15729
16244
  const candidates2 = [
15730
- join27(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
15731
- join27(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
16245
+ join28(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
16246
+ join28(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
15732
16247
  ];
15733
16248
  for (const p of candidates2) {
15734
- if (existsSync19(p))
16249
+ if (existsSync20(p))
15735
16250
  return p;
15736
16251
  }
15737
16252
  } catch {
15738
16253
  }
15739
- const nvmBase = join27(homedir8(), ".nvm", "versions", "node");
15740
- if (existsSync19(nvmBase)) {
16254
+ const nvmBase = join28(homedir8(), ".nvm", "versions", "node");
16255
+ if (existsSync20(nvmBase)) {
15741
16256
  try {
15742
16257
  for (const ver of readdirSync6(nvmBase)) {
15743
- const p = join27(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
15744
- if (existsSync19(p))
16258
+ const p = join28(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
16259
+ if (existsSync20(p))
15745
16260
  return p;
15746
16261
  }
15747
16262
  } catch {
@@ -15754,21 +16269,21 @@ function ensureTranscribeCliBackground() {
15754
16269
  return;
15755
16270
  _bgInstallPromise = (async () => {
15756
16271
  try {
15757
- const globalRoot = execSync17("npm root -g", {
16272
+ const globalRoot = execSync18("npm root -g", {
15758
16273
  encoding: "utf-8",
15759
16274
  timeout: 5e3,
15760
16275
  stdio: ["pipe", "pipe", "pipe"]
15761
16276
  }).trim();
15762
- if (existsSync19(join27(globalRoot, "transcribe-cli", "dist", "index.js"))) {
16277
+ if (existsSync20(join28(globalRoot, "transcribe-cli", "dist", "index.js"))) {
15763
16278
  return true;
15764
16279
  }
15765
16280
  } catch {
15766
16281
  }
15767
16282
  try {
15768
16283
  const { exec } = await import("node:child_process");
15769
- return new Promise((resolve26) => {
16284
+ return new Promise((resolve27) => {
15770
16285
  exec("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
15771
- resolve26(!err);
16286
+ resolve27(!err);
15772
16287
  });
15773
16288
  });
15774
16289
  } catch {
@@ -15821,11 +16336,11 @@ var init_listen = __esm({
15821
16336
  return this._ready;
15822
16337
  }
15823
16338
  async start() {
15824
- return new Promise((resolve26, reject) => {
16339
+ return new Promise((resolve27, reject) => {
15825
16340
  const timeout = setTimeout(() => {
15826
16341
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
15827
16342
  }, 3e5);
15828
- this.process = spawn8("python3", [
16343
+ this.process = spawn9("python3", [
15829
16344
  this.scriptPath,
15830
16345
  "--model",
15831
16346
  this.model,
@@ -15849,7 +16364,7 @@ var init_listen = __esm({
15849
16364
  this._ready = true;
15850
16365
  clearTimeout(timeout);
15851
16366
  this.emit("ready");
15852
- resolve26();
16367
+ resolve27();
15853
16368
  break;
15854
16369
  case "transcript":
15855
16370
  this.emit("transcript", {
@@ -15954,7 +16469,7 @@ var init_listen = __esm({
15954
16469
  }
15955
16470
  if (!this.transcribeCliAvailable) {
15956
16471
  try {
15957
- execSync17("which transcribe-cli", { stdio: "pipe" });
16472
+ execSync18("which transcribe-cli", { stdio: "pipe" });
15958
16473
  this.transcribeCliAvailable = true;
15959
16474
  } catch {
15960
16475
  this.transcribeCliAvailable = false;
@@ -15971,29 +16486,29 @@ var init_listen = __esm({
15971
16486
  } catch {
15972
16487
  }
15973
16488
  try {
15974
- const globalRoot = execSync17("npm root -g", {
16489
+ const globalRoot = execSync18("npm root -g", {
15975
16490
  encoding: "utf-8",
15976
16491
  timeout: 5e3,
15977
16492
  stdio: ["pipe", "pipe", "pipe"]
15978
16493
  }).trim();
15979
- const tcPath = join27(globalRoot, "transcribe-cli");
15980
- if (existsSync19(join27(tcPath, "dist", "index.js"))) {
16494
+ const tcPath = join28(globalRoot, "transcribe-cli");
16495
+ if (existsSync20(join28(tcPath, "dist", "index.js"))) {
15981
16496
  const { createRequire: createRequire4 } = await import("node:module");
15982
16497
  const req = createRequire4(import.meta.url);
15983
- return req(join27(tcPath, "dist", "index.js"));
16498
+ return req(join28(tcPath, "dist", "index.js"));
15984
16499
  }
15985
16500
  } catch {
15986
16501
  }
15987
- const nvmBase = join27(homedir8(), ".nvm", "versions", "node");
15988
- if (existsSync19(nvmBase)) {
16502
+ const nvmBase = join28(homedir8(), ".nvm", "versions", "node");
16503
+ if (existsSync20(nvmBase)) {
15989
16504
  try {
15990
16505
  const { readdirSync: readdirSync14 } = await import("node:fs");
15991
16506
  for (const ver of readdirSync14(nvmBase)) {
15992
- const tcPath = join27(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
15993
- if (existsSync19(join27(tcPath, "dist", "index.js"))) {
16507
+ const tcPath = join28(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
16508
+ if (existsSync20(join28(tcPath, "dist", "index.js"))) {
15994
16509
  const { createRequire: createRequire4 } = await import("node:module");
15995
16510
  const req = createRequire4(import.meta.url);
15996
- return req(join27(tcPath, "dist", "index.js"));
16511
+ return req(join28(tcPath, "dist", "index.js"));
15997
16512
  }
15998
16513
  }
15999
16514
  } catch {
@@ -16021,7 +16536,7 @@ var init_listen = __esm({
16021
16536
  }
16022
16537
  if (!tc) {
16023
16538
  try {
16024
- execSync17("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
16539
+ execSync18("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
16025
16540
  this.transcribeCliAvailable = null;
16026
16541
  tc = await this.loadTranscribeCli();
16027
16542
  } catch {
@@ -16053,11 +16568,11 @@ var init_listen = __esm({
16053
16568
  this.liveTranscriber.on("error", (err) => {
16054
16569
  this.emit("error", err);
16055
16570
  });
16056
- await new Promise((resolve26, reject) => {
16571
+ await new Promise((resolve27, reject) => {
16057
16572
  const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
16058
16573
  this.liveTranscriber.on("ready", () => {
16059
16574
  clearTimeout(timeout);
16060
- resolve26();
16575
+ resolve27();
16061
16576
  });
16062
16577
  this.liveTranscriber.on("error", (err) => {
16063
16578
  clearTimeout(timeout);
@@ -16107,7 +16622,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
16107
16622
  return `Failed to start live transcription: ${msg}${tcHint}`;
16108
16623
  }
16109
16624
  }
16110
- this.micProcess = spawn8(micCmd.cmd, micCmd.args, {
16625
+ this.micProcess = spawn9(micCmd.cmd, micCmd.args, {
16111
16626
  stdio: ["pipe", "pipe", "pipe"],
16112
16627
  env: { ...process.env }
16113
16628
  });
@@ -16202,7 +16717,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
16202
16717
  }
16203
16718
  if (!tc) {
16204
16719
  try {
16205
- execSync17("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
16720
+ execSync18("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
16206
16721
  this.transcribeCliAvailable = null;
16207
16722
  tc = await this.loadTranscribeCli();
16208
16723
  } catch {
@@ -16219,10 +16734,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
16219
16734
  });
16220
16735
  if (outputDir) {
16221
16736
  const { basename: basename16 } = await import("node:path");
16222
- const transcriptDir = join27(outputDir, ".oa", "transcripts");
16223
- mkdirSync5(transcriptDir, { recursive: true });
16224
- const outFile = join27(transcriptDir, `${basename16(filePath)}.txt`);
16225
- writeFileSync5(outFile, result.text, "utf-8");
16737
+ const transcriptDir = join28(outputDir, ".oa", "transcripts");
16738
+ mkdirSync6(transcriptDir, { recursive: true });
16739
+ const outFile = join28(transcriptDir, `${basename16(filePath)}.txt`);
16740
+ writeFileSync6(outFile, result.text, "utf-8");
16226
16741
  }
16227
16742
  return {
16228
16743
  text: result.text,
@@ -17538,8 +18053,8 @@ Approach this task thoughtfully:
17538
18053
  });
17539
18054
 
17540
18055
  // packages/prompts/dist/index.js
17541
- import { join as join28, dirname as dirname10 } from "node:path";
17542
- import { fileURLToPath as fileURLToPath7 } from "node:url";
18056
+ import { join as join29, dirname as dirname11 } from "node:path";
18057
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
17543
18058
  var _dir, _packageRoot;
17544
18059
  var init_dist6 = __esm({
17545
18060
  "packages/prompts/dist/index.js"() {
@@ -17548,27 +18063,27 @@ var init_dist6 = __esm({
17548
18063
  init_render2();
17549
18064
  init_task_templates();
17550
18065
  init_render2();
17551
- _dir = dirname10(fileURLToPath7(import.meta.url));
17552
- _packageRoot = join28(_dir, "..");
18066
+ _dir = dirname11(fileURLToPath8(import.meta.url));
18067
+ _packageRoot = join29(_dir, "..");
17553
18068
  }
17554
18069
  });
17555
18070
 
17556
18071
  // packages/cli/dist/tui/oa-directory.js
17557
- import { existsSync as existsSync20, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
17558
- import { join as join29, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
18072
+ import { existsSync as existsSync21, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync7, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
18073
+ import { join as join30, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
17559
18074
  import { homedir as homedir9 } from "node:os";
17560
18075
  function initOaDirectory(repoRoot) {
17561
- const oaPath = join29(repoRoot, OA_DIR);
18076
+ const oaPath = join30(repoRoot, OA_DIR);
17562
18077
  for (const sub of SUBDIRS) {
17563
- mkdirSync6(join29(oaPath, sub), { recursive: true });
18078
+ mkdirSync7(join30(oaPath, sub), { recursive: true });
17564
18079
  }
17565
18080
  try {
17566
- const gitignorePath = join29(repoRoot, ".gitignore");
18081
+ const gitignorePath = join30(repoRoot, ".gitignore");
17567
18082
  const settingsPattern = ".oa/settings.json";
17568
- if (existsSync20(gitignorePath)) {
17569
- const content = readFileSync14(gitignorePath, "utf-8");
18083
+ if (existsSync21(gitignorePath)) {
18084
+ const content = readFileSync15(gitignorePath, "utf-8");
17570
18085
  if (!content.includes(settingsPattern)) {
17571
- writeFileSync6(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
18086
+ writeFileSync7(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
17572
18087
  }
17573
18088
  }
17574
18089
  } catch {
@@ -17576,41 +18091,41 @@ function initOaDirectory(repoRoot) {
17576
18091
  return oaPath;
17577
18092
  }
17578
18093
  function hasOaDirectory(repoRoot) {
17579
- return existsSync20(join29(repoRoot, OA_DIR, "index"));
18094
+ return existsSync21(join30(repoRoot, OA_DIR, "index"));
17580
18095
  }
17581
18096
  function loadProjectSettings(repoRoot) {
17582
- const settingsPath = join29(repoRoot, OA_DIR, "settings.json");
18097
+ const settingsPath = join30(repoRoot, OA_DIR, "settings.json");
17583
18098
  try {
17584
- if (existsSync20(settingsPath)) {
17585
- return JSON.parse(readFileSync14(settingsPath, "utf-8"));
18099
+ if (existsSync21(settingsPath)) {
18100
+ return JSON.parse(readFileSync15(settingsPath, "utf-8"));
17586
18101
  }
17587
18102
  } catch {
17588
18103
  }
17589
18104
  return {};
17590
18105
  }
17591
18106
  function saveProjectSettings(repoRoot, settings) {
17592
- const oaPath = join29(repoRoot, OA_DIR);
17593
- mkdirSync6(oaPath, { recursive: true });
18107
+ const oaPath = join30(repoRoot, OA_DIR);
18108
+ mkdirSync7(oaPath, { recursive: true });
17594
18109
  const existing = loadProjectSettings(repoRoot);
17595
18110
  const merged = { ...existing, ...settings };
17596
- writeFileSync6(join29(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
18111
+ writeFileSync7(join30(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
17597
18112
  }
17598
18113
  function loadGlobalSettings() {
17599
- const settingsPath = join29(homedir9(), ".open-agents", "settings.json");
18114
+ const settingsPath = join30(homedir9(), ".open-agents", "settings.json");
17600
18115
  try {
17601
- if (existsSync20(settingsPath)) {
17602
- return JSON.parse(readFileSync14(settingsPath, "utf-8"));
18116
+ if (existsSync21(settingsPath)) {
18117
+ return JSON.parse(readFileSync15(settingsPath, "utf-8"));
17603
18118
  }
17604
18119
  } catch {
17605
18120
  }
17606
18121
  return {};
17607
18122
  }
17608
18123
  function saveGlobalSettings(settings) {
17609
- const dir = join29(homedir9(), ".open-agents");
17610
- mkdirSync6(dir, { recursive: true });
18124
+ const dir = join30(homedir9(), ".open-agents");
18125
+ mkdirSync7(dir, { recursive: true });
17611
18126
  const existing = loadGlobalSettings();
17612
18127
  const merged = { ...existing, ...settings };
17613
- writeFileSync6(join29(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
18128
+ writeFileSync7(join30(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
17614
18129
  }
17615
18130
  function resolveSettings(repoRoot) {
17616
18131
  const global = loadGlobalSettings();
@@ -17625,12 +18140,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
17625
18140
  while (dir && !visited.has(dir)) {
17626
18141
  visited.add(dir);
17627
18142
  for (const name of CONTEXT_FILES) {
17628
- const filePath = join29(dir, name);
18143
+ const filePath = join30(dir, name);
17629
18144
  const normalizedName = name.toLowerCase();
17630
- if (existsSync20(filePath) && !seen.has(filePath)) {
18145
+ if (existsSync21(filePath) && !seen.has(filePath)) {
17631
18146
  seen.add(filePath);
17632
18147
  try {
17633
- let content = readFileSync14(filePath, "utf-8");
18148
+ let content = readFileSync15(filePath, "utf-8");
17634
18149
  if (content.length > maxContentLen) {
17635
18150
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
17636
18151
  }
@@ -17644,11 +18159,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
17644
18159
  }
17645
18160
  }
17646
18161
  }
17647
- const projectMap = join29(dir, OA_DIR, "context", "project-map.md");
17648
- if (existsSync20(projectMap) && !seen.has(projectMap)) {
18162
+ const projectMap = join30(dir, OA_DIR, "context", "project-map.md");
18163
+ if (existsSync21(projectMap) && !seen.has(projectMap)) {
17649
18164
  seen.add(projectMap);
17650
18165
  try {
17651
- let content = readFileSync14(projectMap, "utf-8");
18166
+ let content = readFileSync15(projectMap, "utf-8");
17652
18167
  if (content.length > maxContentLen) {
17653
18168
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
17654
18169
  }
@@ -17660,7 +18175,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
17660
18175
  } catch {
17661
18176
  }
17662
18177
  }
17663
- const parent = join29(dir, "..");
18178
+ const parent = join30(dir, "..");
17664
18179
  if (parent === dir)
17665
18180
  break;
17666
18181
  dir = parent;
@@ -17678,9 +18193,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
17678
18193
  return found;
17679
18194
  }
17680
18195
  function readIndexMeta(repoRoot) {
17681
- const metaPath = join29(repoRoot, OA_DIR, "index", "meta.json");
18196
+ const metaPath = join30(repoRoot, OA_DIR, "index", "meta.json");
17682
18197
  try {
17683
- return JSON.parse(readFileSync14(metaPath, "utf-8"));
18198
+ return JSON.parse(readFileSync15(metaPath, "utf-8"));
17684
18199
  } catch {
17685
18200
  return null;
17686
18201
  }
@@ -17731,28 +18246,28 @@ ${tree}\`\`\`
17731
18246
  sections.push("");
17732
18247
  }
17733
18248
  const content = sections.join("\n");
17734
- const contextDir = join29(repoRoot, OA_DIR, "context");
17735
- mkdirSync6(contextDir, { recursive: true });
17736
- writeFileSync6(join29(contextDir, "project-map.md"), content, "utf-8");
18249
+ const contextDir = join30(repoRoot, OA_DIR, "context");
18250
+ mkdirSync7(contextDir, { recursive: true });
18251
+ writeFileSync7(join30(contextDir, "project-map.md"), content, "utf-8");
17737
18252
  return content;
17738
18253
  }
17739
18254
  function saveSession(repoRoot, session) {
17740
- const historyDir = join29(repoRoot, OA_DIR, "history");
17741
- mkdirSync6(historyDir, { recursive: true });
17742
- writeFileSync6(join29(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
18255
+ const historyDir = join30(repoRoot, OA_DIR, "history");
18256
+ mkdirSync7(historyDir, { recursive: true });
18257
+ writeFileSync7(join30(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
17743
18258
  }
17744
18259
  function loadRecentSessions(repoRoot, limit = 5) {
17745
- const historyDir = join29(repoRoot, OA_DIR, "history");
17746
- if (!existsSync20(historyDir))
18260
+ const historyDir = join30(repoRoot, OA_DIR, "history");
18261
+ if (!existsSync21(historyDir))
17747
18262
  return [];
17748
18263
  try {
17749
18264
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
17750
- const stat5 = statSync9(join29(historyDir, f));
18265
+ const stat5 = statSync9(join30(historyDir, f));
17751
18266
  return { file: f, mtime: stat5.mtimeMs };
17752
18267
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
17753
18268
  return files.map((f) => {
17754
18269
  try {
17755
- return JSON.parse(readFileSync14(join29(historyDir, f.file), "utf-8"));
18270
+ return JSON.parse(readFileSync15(join30(historyDir, f.file), "utf-8"));
17756
18271
  } catch {
17757
18272
  return null;
17758
18273
  }
@@ -17762,16 +18277,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
17762
18277
  }
17763
18278
  }
17764
18279
  function savePendingTask(repoRoot, task) {
17765
- const historyDir = join29(repoRoot, OA_DIR, "history");
17766
- mkdirSync6(historyDir, { recursive: true });
17767
- writeFileSync6(join29(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
18280
+ const historyDir = join30(repoRoot, OA_DIR, "history");
18281
+ mkdirSync7(historyDir, { recursive: true });
18282
+ writeFileSync7(join30(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
17768
18283
  }
17769
18284
  function loadPendingTask(repoRoot) {
17770
- const filePath = join29(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
18285
+ const filePath = join30(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
17771
18286
  try {
17772
- if (!existsSync20(filePath))
18287
+ if (!existsSync21(filePath))
17773
18288
  return null;
17774
- const data = JSON.parse(readFileSync14(filePath, "utf-8"));
18289
+ const data = JSON.parse(readFileSync15(filePath, "utf-8"));
17775
18290
  try {
17776
18291
  unlinkSync3(filePath);
17777
18292
  } catch {
@@ -17782,13 +18297,13 @@ function loadPendingTask(repoRoot) {
17782
18297
  }
17783
18298
  }
17784
18299
  function saveSessionContext(repoRoot, entry) {
17785
- const contextDir = join29(repoRoot, OA_DIR, "context");
17786
- mkdirSync6(contextDir, { recursive: true });
17787
- const filePath = join29(contextDir, CONTEXT_SAVE_FILE);
18300
+ const contextDir = join30(repoRoot, OA_DIR, "context");
18301
+ mkdirSync7(contextDir, { recursive: true });
18302
+ const filePath = join30(contextDir, CONTEXT_SAVE_FILE);
17788
18303
  let ctx;
17789
18304
  try {
17790
- if (existsSync20(filePath)) {
17791
- ctx = JSON.parse(readFileSync14(filePath, "utf-8"));
18305
+ if (existsSync21(filePath)) {
18306
+ ctx = JSON.parse(readFileSync15(filePath, "utf-8"));
17792
18307
  } else {
17793
18308
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
17794
18309
  }
@@ -17800,14 +18315,14 @@ function saveSessionContext(repoRoot, entry) {
17800
18315
  ctx.entries = ctx.entries.slice(-ctx.maxEntries);
17801
18316
  }
17802
18317
  ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
17803
- writeFileSync6(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
18318
+ writeFileSync7(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
17804
18319
  }
17805
18320
  function loadSessionContext(repoRoot) {
17806
- const filePath = join29(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
18321
+ const filePath = join30(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
17807
18322
  try {
17808
- if (!existsSync20(filePath))
18323
+ if (!existsSync21(filePath))
17809
18324
  return null;
17810
- return JSON.parse(readFileSync14(filePath, "utf-8"));
18325
+ return JSON.parse(readFileSync15(filePath, "utf-8"));
17811
18326
  } catch {
17812
18327
  return null;
17813
18328
  }
@@ -17854,12 +18369,12 @@ function detectManifests(repoRoot) {
17854
18369
  { file: "docker-compose.yaml", type: "Docker Compose" }
17855
18370
  ];
17856
18371
  for (const check of checks) {
17857
- const filePath = join29(repoRoot, check.file);
17858
- if (existsSync20(filePath)) {
18372
+ const filePath = join30(repoRoot, check.file);
18373
+ if (existsSync21(filePath)) {
17859
18374
  let name;
17860
18375
  if (check.nameField) {
17861
18376
  try {
17862
- const data = JSON.parse(readFileSync14(filePath, "utf-8"));
18377
+ const data = JSON.parse(readFileSync15(filePath, "utf-8"));
17863
18378
  name = data[check.nameField];
17864
18379
  } catch {
17865
18380
  }
@@ -17888,7 +18403,7 @@ function findKeyFiles(repoRoot) {
17888
18403
  { pattern: "CLAUDE.md", description: "Claude Code context" }
17889
18404
  ];
17890
18405
  for (const check of checks) {
17891
- if (existsSync20(join29(repoRoot, check.pattern))) {
18406
+ if (existsSync21(join30(repoRoot, check.pattern))) {
17892
18407
  keyFiles.push({ path: check.pattern, description: check.description });
17893
18408
  }
17894
18409
  }
@@ -17914,12 +18429,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
17914
18429
  if (entry.isDirectory()) {
17915
18430
  let fileCount = 0;
17916
18431
  try {
17917
- fileCount = readdirSync7(join29(root, entry.name)).filter((f) => !f.startsWith(".")).length;
18432
+ fileCount = readdirSync7(join30(root, entry.name)).filter((f) => !f.startsWith(".")).length;
17918
18433
  } catch {
17919
18434
  }
17920
18435
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
17921
18436
  `;
17922
- result += buildDirTree(join29(root, entry.name), maxDepth, childPrefix, depth + 1);
18437
+ result += buildDirTree(join30(root, entry.name), maxDepth, childPrefix, depth + 1);
17923
18438
  } else if (depth < maxDepth) {
17924
18439
  result += `${prefix}${connector}${entry.name}
17925
18440
  `;
@@ -17972,9 +18487,9 @@ var init_oa_directory = __esm({
17972
18487
 
17973
18488
  // packages/cli/dist/tui/setup.js
17974
18489
  import * as readline from "node:readline";
17975
- import { execSync as execSync18, spawn as spawn9 } from "node:child_process";
17976
- import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
17977
- import { join as join30 } from "node:path";
18490
+ import { execSync as execSync19, spawn as spawn10 } from "node:child_process";
18491
+ import { existsSync as existsSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "node:fs";
18492
+ import { join as join31 } from "node:path";
17978
18493
  import { homedir as homedir10, platform } from "node:os";
17979
18494
  function detectSystemSpecs() {
17980
18495
  let totalRamGB = 0;
@@ -17982,7 +18497,7 @@ function detectSystemSpecs() {
17982
18497
  let gpuVramGB = 0;
17983
18498
  let gpuName = "";
17984
18499
  try {
17985
- const memInfo = execSync18("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
18500
+ const memInfo = execSync19("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
17986
18501
  encoding: "utf8",
17987
18502
  timeout: 5e3
17988
18503
  });
@@ -18002,7 +18517,7 @@ function detectSystemSpecs() {
18002
18517
  } catch {
18003
18518
  }
18004
18519
  try {
18005
- const nvidiaSmi = execSync18("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
18520
+ const nvidiaSmi = execSync19("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
18006
18521
  const lines = nvidiaSmi.trim().split("\n");
18007
18522
  if (lines.length > 0) {
18008
18523
  for (const line of lines) {
@@ -18058,12 +18573,12 @@ function modelSupportsToolCalling(modelName) {
18058
18573
  return false;
18059
18574
  }
18060
18575
  function ask(rl, question) {
18061
- return new Promise((resolve26) => {
18062
- rl.question(question, (answer) => resolve26(answer.trim()));
18576
+ return new Promise((resolve27) => {
18577
+ rl.question(question, (answer) => resolve27(answer.trim()));
18063
18578
  });
18064
18579
  }
18065
18580
  function askSecret(rl, question) {
18066
- return new Promise((resolve26) => {
18581
+ return new Promise((resolve27) => {
18067
18582
  process.stdout.write(question);
18068
18583
  let secret = "";
18069
18584
  const stdin = process.stdin;
@@ -18081,7 +18596,7 @@ function askSecret(rl, question) {
18081
18596
  stdin.setRawMode(hadRawMode ?? false);
18082
18597
  }
18083
18598
  process.stdout.write("\n");
18084
- resolve26(secret.trim());
18599
+ resolve27(secret.trim());
18085
18600
  return;
18086
18601
  } else if (c3 === "") {
18087
18602
  stdin.removeListener("data", onData);
@@ -18089,7 +18604,7 @@ function askSecret(rl, question) {
18089
18604
  stdin.setRawMode(hadRawMode ?? false);
18090
18605
  }
18091
18606
  process.stdout.write("\n");
18092
- resolve26("");
18607
+ resolve27("");
18093
18608
  return;
18094
18609
  } else if (c3 === "\x7F" || c3 === "\b") {
18095
18610
  if (secret.length > 0) {
@@ -18127,7 +18642,7 @@ function installOllamaLinux() {
18127
18642
 
18128
18643
  `);
18129
18644
  try {
18130
- execSync18("curl -fsSL https://ollama.com/install.sh | sh", {
18645
+ execSync19("curl -fsSL https://ollama.com/install.sh | sh", {
18131
18646
  stdio: "inherit",
18132
18647
  timeout: 3e5
18133
18648
  });
@@ -18166,10 +18681,10 @@ async function installOllamaMac(rl) {
18166
18681
 
18167
18682
  `);
18168
18683
  try {
18169
- execSync18('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
18684
+ execSync19('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
18170
18685
  if (!hasCmd("brew")) {
18171
18686
  try {
18172
- const brewPrefix = existsSync21("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
18687
+ const brewPrefix = existsSync22("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
18173
18688
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
18174
18689
  } catch {
18175
18690
  }
@@ -18199,7 +18714,7 @@ async function installOllamaMac(rl) {
18199
18714
 
18200
18715
  `);
18201
18716
  try {
18202
- execSync18("brew install ollama", {
18717
+ execSync19("brew install ollama", {
18203
18718
  stdio: "inherit",
18204
18719
  timeout: 3e5
18205
18720
  });
@@ -18226,7 +18741,7 @@ function installOllamaWindows() {
18226
18741
 
18227
18742
  `);
18228
18743
  try {
18229
- execSync18('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
18744
+ execSync19('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
18230
18745
  stdio: "inherit",
18231
18746
  timeout: 3e5
18232
18747
  });
@@ -18249,7 +18764,7 @@ function installOllamaWindows() {
18249
18764
  }
18250
18765
  function pullModelWithAutoUpdate(tag) {
18251
18766
  try {
18252
- execSync18(`ollama pull ${tag}`, {
18767
+ execSync19(`ollama pull ${tag}`, {
18253
18768
  stdio: "inherit",
18254
18769
  timeout: 36e5
18255
18770
  // 1 hour max
@@ -18266,7 +18781,7 @@ function pullModelWithAutoUpdate(tag) {
18266
18781
 
18267
18782
  `);
18268
18783
  try {
18269
- execSync18("curl -fsSL https://ollama.com/install.sh | sh", {
18784
+ execSync19("curl -fsSL https://ollama.com/install.sh | sh", {
18270
18785
  stdio: "inherit",
18271
18786
  timeout: 3e5
18272
18787
  // 5 min max for install
@@ -18277,7 +18792,7 @@ function pullModelWithAutoUpdate(tag) {
18277
18792
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
18278
18793
 
18279
18794
  `);
18280
- execSync18(`ollama pull ${tag}`, {
18795
+ execSync19(`ollama pull ${tag}`, {
18281
18796
  stdio: "inherit",
18282
18797
  timeout: 36e5
18283
18798
  });
@@ -18458,9 +18973,9 @@ async function doSetup(config, rl) {
18458
18973
  ${c2.cyan("\u25CF")} Starting ollama serve in background...
18459
18974
  `);
18460
18975
  try {
18461
- const child = spawn9("ollama", ["serve"], { stdio: "ignore", detached: true });
18976
+ const child = spawn10("ollama", ["serve"], { stdio: "ignore", detached: true });
18462
18977
  child.unref();
18463
- await new Promise((resolve26) => setTimeout(resolve26, 3e3));
18978
+ await new Promise((resolve27) => setTimeout(resolve27, 3e3));
18464
18979
  try {
18465
18980
  models = await fetchOllamaModels(config.backendUrl);
18466
18981
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -18486,9 +19001,9 @@ async function doSetup(config, rl) {
18486
19001
  ${c2.cyan("\u25CF")} Starting ollama serve...
18487
19002
  `);
18488
19003
  try {
18489
- const child = spawn9("ollama", ["serve"], { stdio: "ignore", detached: true });
19004
+ const child = spawn10("ollama", ["serve"], { stdio: "ignore", detached: true });
18490
19005
  child.unref();
18491
- await new Promise((resolve26) => setTimeout(resolve26, 3e3));
19006
+ await new Promise((resolve27) => setTimeout(resolve27, 3e3));
18492
19007
  try {
18493
19008
  models = await fetchOllamaModels(config.backendUrl);
18494
19009
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -18643,12 +19158,12 @@ async function doSetup(config, rl) {
18643
19158
  `PARAMETER num_predict ${numPredict}`,
18644
19159
  `PARAMETER stop "<|endoftext|>"`
18645
19160
  ].join("\n");
18646
- const modelDir2 = join30(homedir10(), ".open-agents", "models");
18647
- mkdirSync7(modelDir2, { recursive: true });
18648
- const modelfilePath = join30(modelDir2, `Modelfile.${customName}`);
18649
- writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
19161
+ const modelDir2 = join31(homedir10(), ".open-agents", "models");
19162
+ mkdirSync8(modelDir2, { recursive: true });
19163
+ const modelfilePath = join31(modelDir2, `Modelfile.${customName}`);
19164
+ writeFileSync8(modelfilePath, modelfileContent + "\n", "utf8");
18650
19165
  process.stdout.write(` ${c2.dim("Creating model...")} `);
18651
- execSync18(`ollama create ${customName} -f ${modelfilePath}`, {
19166
+ execSync19(`ollama create ${customName} -f ${modelfilePath}`, {
18652
19167
  stdio: "pipe",
18653
19168
  timeout: 12e4
18654
19169
  });
@@ -18691,7 +19206,7 @@ async function isModelAvailable(config) {
18691
19206
  }
18692
19207
  function isFirstRun() {
18693
19208
  try {
18694
- return !existsSync21(join30(homedir10(), ".open-agents", "config.json"));
19209
+ return !existsSync22(join31(homedir10(), ".open-agents", "config.json"));
18695
19210
  } catch {
18696
19211
  return true;
18697
19212
  }
@@ -18699,7 +19214,7 @@ function isFirstRun() {
18699
19214
  function hasCmd(cmd) {
18700
19215
  try {
18701
19216
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
18702
- execSync18(whichCmd, { stdio: "pipe", timeout: 3e3 });
19217
+ execSync19(whichCmd, { stdio: "pipe", timeout: 3e3 });
18703
19218
  return true;
18704
19219
  } catch {
18705
19220
  return false;
@@ -18728,11 +19243,11 @@ function detectPkgManager() {
18728
19243
  return null;
18729
19244
  }
18730
19245
  function getVenvDir() {
18731
- return join30(homedir10(), ".open-agents", "venv");
19246
+ return join31(homedir10(), ".open-agents", "venv");
18732
19247
  }
18733
19248
  function hasVenvModule() {
18734
19249
  try {
18735
- execSync18("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
19250
+ execSync19("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
18736
19251
  return true;
18737
19252
  } catch {
18738
19253
  return false;
@@ -18740,8 +19255,8 @@ function hasVenvModule() {
18740
19255
  }
18741
19256
  function ensureVenv(log) {
18742
19257
  const venvDir = getVenvDir();
18743
- const venvPip = join30(venvDir, "bin", "pip");
18744
- if (existsSync21(venvPip))
19258
+ const venvPip = join31(venvDir, "bin", "pip");
19259
+ if (existsSync22(venvPip))
18745
19260
  return venvDir;
18746
19261
  log("Creating Python venv for vision deps...");
18747
19262
  if (!hasCmd("python3")) {
@@ -18753,9 +19268,9 @@ function ensureVenv(log) {
18753
19268
  return null;
18754
19269
  }
18755
19270
  try {
18756
- mkdirSync7(join30(homedir10(), ".open-agents"), { recursive: true });
18757
- execSync18(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
18758
- execSync18(`"${join30(venvDir, "bin", "pip")}" install --upgrade pip`, {
19271
+ mkdirSync8(join31(homedir10(), ".open-agents"), { recursive: true });
19272
+ execSync19(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
19273
+ execSync19(`"${join31(venvDir, "bin", "pip")}" install --upgrade pip`, {
18759
19274
  stdio: "pipe",
18760
19275
  timeout: 6e4
18761
19276
  });
@@ -18768,7 +19283,7 @@ function ensureVenv(log) {
18768
19283
  }
18769
19284
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
18770
19285
  try {
18771
- execSync18(`sudo -n ${cmd}`, {
19286
+ execSync19(`sudo -n ${cmd}`, {
18772
19287
  stdio: "pipe",
18773
19288
  timeout: timeoutMs,
18774
19289
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -18780,7 +19295,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
18780
19295
  }
18781
19296
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
18782
19297
  try {
18783
- execSync18(`sudo -S ${cmd}`, {
19298
+ execSync19(`sudo -S ${cmd}`, {
18784
19299
  input: password + "\n",
18785
19300
  stdio: ["pipe", "pipe", "pipe"],
18786
19301
  timeout: timeoutMs,
@@ -18840,7 +19355,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
18840
19355
  } else {
18841
19356
  log("Installing tesseract-ocr...");
18842
19357
  try {
18843
- execSync18(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
19358
+ execSync19(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
18844
19359
  if (hasCmd("tesseract")) {
18845
19360
  log("tesseract-ocr installed successfully.");
18846
19361
  } else {
@@ -18912,7 +19427,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
18912
19427
  } else {
18913
19428
  log(`Installing ${dep.label}...`);
18914
19429
  try {
18915
- execSync18(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
19430
+ execSync19(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
18916
19431
  if (hasCmd(dep.binary)) {
18917
19432
  log(`${dep.label} installed successfully.`);
18918
19433
  } else {
@@ -18943,7 +19458,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
18943
19458
  const venvCmds = {
18944
19459
  apt: () => {
18945
19460
  try {
18946
- const pyVer = execSync18(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
19461
+ const pyVer = execSync19(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
18947
19462
  return `apt-get install -y python3-venv python${pyVer}-venv`;
18948
19463
  } catch {
18949
19464
  return "apt-get install -y python3-venv";
@@ -18964,19 +19479,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
18964
19479
  }
18965
19480
  }
18966
19481
  const venvDir = getVenvDir();
18967
- const venvBin = join30(venvDir, "bin");
18968
- const venvMoondream = join30(venvBin, "moondream-station");
19482
+ const venvBin = join31(venvDir, "bin");
19483
+ const venvMoondream = join31(venvBin, "moondream-station");
18969
19484
  const venv = ensureVenv(log);
18970
- if (venv && !hasCmd("moondream-station") && !existsSync21(venvMoondream)) {
18971
- const venvPip = join30(venvBin, "pip");
19485
+ if (venv && !hasCmd("moondream-station") && !existsSync22(venvMoondream)) {
19486
+ const venvPip = join31(venvBin, "pip");
18972
19487
  log("Installing moondream-station in ~/.open-agents/venv...");
18973
19488
  try {
18974
- execSync18(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
18975
- if (existsSync21(venvMoondream)) {
19489
+ execSync19(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
19490
+ if (existsSync22(venvMoondream)) {
18976
19491
  log("moondream-station installed successfully.");
18977
19492
  } else {
18978
19493
  try {
18979
- const check = execSync18(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
19494
+ const check = execSync19(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
18980
19495
  if (check.includes("moondream")) {
18981
19496
  log("moondream-station package installed.");
18982
19497
  }
@@ -18989,11 +19504,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
18989
19504
  }
18990
19505
  }
18991
19506
  if (venv) {
18992
- const venvPython = join30(venvBin, "python");
18993
- const venvPip2 = join30(venvBin, "pip");
19507
+ const venvPython = join31(venvBin, "python");
19508
+ const venvPip2 = join31(venvBin, "pip");
18994
19509
  let ocrStackInstalled = false;
18995
19510
  try {
18996
- execSync18(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
19511
+ execSync19(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
18997
19512
  ocrStackInstalled = true;
18998
19513
  } catch {
18999
19514
  }
@@ -19001,9 +19516,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
19001
19516
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
19002
19517
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
19003
19518
  try {
19004
- execSync18(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
19519
+ execSync19(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
19005
19520
  try {
19006
- execSync18(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
19521
+ execSync19(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
19007
19522
  log("OCR Python stack installed successfully.");
19008
19523
  } catch {
19009
19524
  log("OCR Python stack install completed but import verification failed.");
@@ -19050,11 +19565,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
19050
19565
  `PARAMETER num_predict ${numPredict}`,
19051
19566
  `PARAMETER stop "<|endoftext|>"`
19052
19567
  ].join("\n");
19053
- const modelDir2 = join30(homedir10(), ".open-agents", "models");
19054
- mkdirSync7(modelDir2, { recursive: true });
19055
- const modelfilePath = join30(modelDir2, `Modelfile.${customName}`);
19056
- writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
19057
- execSync18(`ollama create ${customName} -f ${modelfilePath}`, {
19568
+ const modelDir2 = join31(homedir10(), ".open-agents", "models");
19569
+ mkdirSync8(modelDir2, { recursive: true });
19570
+ const modelfilePath = join31(modelDir2, `Modelfile.${customName}`);
19571
+ writeFileSync8(modelfilePath, modelfileContent + "\n", "utf8");
19572
+ execSync19(`ollama create ${customName} -f ${modelfilePath}`, {
19058
19573
  stdio: "pipe",
19059
19574
  timeout: 12e4
19060
19575
  });
@@ -19941,18 +20456,18 @@ async function handleUpdate(subcommand, ctx) {
19941
20456
  let currentVersion = "0.0.0";
19942
20457
  try {
19943
20458
  const { createRequire: createRequire4 } = await import("node:module");
19944
- const { fileURLToPath: fileURLToPath10 } = await import("node:url");
19945
- const { dirname: dirname13, join: join43 } = await import("node:path");
19946
- const { existsSync: existsSync30 } = await import("node:fs");
20459
+ const { fileURLToPath: fileURLToPath11 } = await import("node:url");
20460
+ const { dirname: dirname14, join: join44 } = await import("node:path");
20461
+ const { existsSync: existsSync31 } = await import("node:fs");
19947
20462
  const req = createRequire4(import.meta.url);
19948
- const thisDir = dirname13(fileURLToPath10(import.meta.url));
20463
+ const thisDir = dirname14(fileURLToPath11(import.meta.url));
19949
20464
  const candidates = [
19950
- join43(thisDir, "..", "package.json"),
19951
- join43(thisDir, "..", "..", "package.json"),
19952
- join43(thisDir, "..", "..", "..", "package.json")
20465
+ join44(thisDir, "..", "package.json"),
20466
+ join44(thisDir, "..", "..", "package.json"),
20467
+ join44(thisDir, "..", "..", "..", "package.json")
19953
20468
  ];
19954
20469
  for (const pkgPath of candidates) {
19955
- if (existsSync30(pkgPath)) {
20470
+ if (existsSync31(pkgPath)) {
19956
20471
  const pkg = req(pkgPath);
19957
20472
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
19958
20473
  currentVersion = pkg.version ?? "0.0.0";
@@ -19990,8 +20505,8 @@ async function handleUpdate(subcommand, ctx) {
19990
20505
  checkSpinner.stop(`Update available: v${info.currentVersion} \u2192 v${c2.bold(c2.green(info.latestVersion))}`);
19991
20506
  const installSpinner = startInlineSpinner("Installing update");
19992
20507
  const { exec } = await import("node:child_process");
19993
- const installOk = await new Promise((resolve26) => {
19994
- const child = exec(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { timeout: 18e4 }, (err) => resolve26(!err));
20508
+ const installOk = await new Promise((resolve27) => {
20509
+ const child = exec(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { timeout: 18e4 }, (err) => resolve27(!err));
19995
20510
  child.stdout?.resume();
19996
20511
  child.stderr?.resume();
19997
20512
  });
@@ -20084,9 +20599,9 @@ var init_commands = __esm({
20084
20599
  });
20085
20600
 
20086
20601
  // packages/cli/dist/tui/project-context.js
20087
- import { existsSync as existsSync22, readFileSync as readFileSync15, readdirSync as readdirSync8 } from "node:fs";
20088
- import { join as join31, basename as basename10 } from "node:path";
20089
- import { execSync as execSync19 } from "node:child_process";
20602
+ import { existsSync as existsSync23, readFileSync as readFileSync16, readdirSync as readdirSync8 } from "node:fs";
20603
+ import { join as join32, basename as basename10 } from "node:path";
20604
+ import { execSync as execSync20 } from "node:child_process";
20090
20605
  import { homedir as homedir11, platform as platform2, release } from "node:os";
20091
20606
  function getModelTier(modelName) {
20092
20607
  const m = modelName.toLowerCase();
@@ -20120,10 +20635,10 @@ function loadProjectMap(repoRoot) {
20120
20635
  if (!hasOaDirectory(repoRoot)) {
20121
20636
  initOaDirectory(repoRoot);
20122
20637
  }
20123
- const mapPath = join31(repoRoot, OA_DIR, "context", "project-map.md");
20124
- if (existsSync22(mapPath)) {
20638
+ const mapPath = join32(repoRoot, OA_DIR, "context", "project-map.md");
20639
+ if (existsSync23(mapPath)) {
20125
20640
  try {
20126
- const content = readFileSync15(mapPath, "utf-8");
20641
+ const content = readFileSync16(mapPath, "utf-8");
20127
20642
  return content;
20128
20643
  } catch {
20129
20644
  }
@@ -20132,19 +20647,19 @@ function loadProjectMap(repoRoot) {
20132
20647
  }
20133
20648
  function getGitInfo(repoRoot) {
20134
20649
  try {
20135
- execSync19("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
20650
+ execSync20("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
20136
20651
  } catch {
20137
20652
  return "";
20138
20653
  }
20139
20654
  const lines = [];
20140
20655
  try {
20141
- const branch = execSync19("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20656
+ const branch = execSync20("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20142
20657
  if (branch)
20143
20658
  lines.push(`Branch: ${branch}`);
20144
20659
  } catch {
20145
20660
  }
20146
20661
  try {
20147
- const status = execSync19("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20662
+ const status = execSync20("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20148
20663
  if (status) {
20149
20664
  const changed = status.split("\n").length;
20150
20665
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -20154,7 +20669,7 @@ function getGitInfo(repoRoot) {
20154
20669
  } catch {
20155
20670
  }
20156
20671
  try {
20157
- const log = execSync19("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20672
+ const log = execSync20("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
20158
20673
  if (log)
20159
20674
  lines.push(`Recent commits:
20160
20675
  ${log}`);
@@ -20164,31 +20679,31 @@ ${log}`);
20164
20679
  }
20165
20680
  function loadMemoryContext(repoRoot) {
20166
20681
  const sections = [];
20167
- const oaMemDir = join31(repoRoot, OA_DIR, "memory");
20682
+ const oaMemDir = join32(repoRoot, OA_DIR, "memory");
20168
20683
  const oaEntries = loadMemoryDir(oaMemDir, "project");
20169
20684
  if (oaEntries)
20170
20685
  sections.push(oaEntries);
20171
- const legacyMemDir = join31(repoRoot, ".open-agents", "memory");
20172
- if (legacyMemDir !== oaMemDir && existsSync22(legacyMemDir)) {
20686
+ const legacyMemDir = join32(repoRoot, ".open-agents", "memory");
20687
+ if (legacyMemDir !== oaMemDir && existsSync23(legacyMemDir)) {
20173
20688
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
20174
20689
  if (legacyEntries)
20175
20690
  sections.push(legacyEntries);
20176
20691
  }
20177
- const globalMemDir = join31(homedir11(), ".open-agents", "memory");
20692
+ const globalMemDir = join32(homedir11(), ".open-agents", "memory");
20178
20693
  const globalEntries = loadMemoryDir(globalMemDir, "global");
20179
20694
  if (globalEntries)
20180
20695
  sections.push(globalEntries);
20181
20696
  return sections.join("\n\n");
20182
20697
  }
20183
20698
  function loadMemoryDir(memDir, scope) {
20184
- if (!existsSync22(memDir))
20699
+ if (!existsSync23(memDir))
20185
20700
  return "";
20186
20701
  const lines = [];
20187
20702
  try {
20188
20703
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
20189
20704
  for (const file of files.slice(0, 10)) {
20190
20705
  try {
20191
- const raw = readFileSync15(join31(memDir, file), "utf-8");
20706
+ const raw = readFileSync16(join32(memDir, file), "utf-8");
20192
20707
  const entries = JSON.parse(raw);
20193
20708
  const topic = basename10(file, ".json");
20194
20709
  const keys = Object.keys(entries);
@@ -21215,22 +21730,22 @@ var init_carousel = __esm({
21215
21730
  });
21216
21731
 
21217
21732
  // packages/cli/dist/tui/carousel-descriptors.js
21218
- import { existsSync as existsSync23, readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
21219
- import { join as join32, basename as basename11 } from "node:path";
21733
+ import { existsSync as existsSync24, readFileSync as readFileSync17, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, readdirSync as readdirSync9 } from "node:fs";
21734
+ import { join as join33, basename as basename11 } from "node:path";
21220
21735
  function loadToolProfile(repoRoot) {
21221
- const filePath = join32(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
21736
+ const filePath = join33(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
21222
21737
  try {
21223
- if (!existsSync23(filePath))
21738
+ if (!existsSync24(filePath))
21224
21739
  return null;
21225
- return JSON.parse(readFileSync16(filePath, "utf-8"));
21740
+ return JSON.parse(readFileSync17(filePath, "utf-8"));
21226
21741
  } catch {
21227
21742
  return null;
21228
21743
  }
21229
21744
  }
21230
21745
  function saveToolProfile(repoRoot, profile) {
21231
- const contextDir = join32(repoRoot, OA_DIR, "context");
21232
- mkdirSync8(contextDir, { recursive: true });
21233
- writeFileSync8(join32(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
21746
+ const contextDir = join33(repoRoot, OA_DIR, "context");
21747
+ mkdirSync9(contextDir, { recursive: true });
21748
+ writeFileSync9(join33(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
21234
21749
  }
21235
21750
  function categorizeToolCall(toolName) {
21236
21751
  for (const cat of TOOL_CATEGORIES) {
@@ -21288,25 +21803,25 @@ function weightedColor(profile) {
21288
21803
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
21289
21804
  }
21290
21805
  function loadCachedDescriptors(repoRoot) {
21291
- const filePath = join32(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
21806
+ const filePath = join33(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
21292
21807
  try {
21293
- if (!existsSync23(filePath))
21808
+ if (!existsSync24(filePath))
21294
21809
  return null;
21295
- const cached = JSON.parse(readFileSync16(filePath, "utf-8"));
21810
+ const cached = JSON.parse(readFileSync17(filePath, "utf-8"));
21296
21811
  return cached.phrases.length > 0 ? cached.phrases : null;
21297
21812
  } catch {
21298
21813
  return null;
21299
21814
  }
21300
21815
  }
21301
21816
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
21302
- const contextDir = join32(repoRoot, OA_DIR, "context");
21303
- mkdirSync8(contextDir, { recursive: true });
21817
+ const contextDir = join33(repoRoot, OA_DIR, "context");
21818
+ mkdirSync9(contextDir, { recursive: true });
21304
21819
  const cached = {
21305
21820
  phrases,
21306
21821
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
21307
21822
  sourceHash
21308
21823
  };
21309
- writeFileSync8(join32(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
21824
+ writeFileSync9(join33(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
21310
21825
  }
21311
21826
  function generateDescriptors(repoRoot) {
21312
21827
  const profile = loadToolProfile(repoRoot);
@@ -21354,11 +21869,11 @@ function generateDescriptors(repoRoot) {
21354
21869
  return phrases;
21355
21870
  }
21356
21871
  function extractFromPackageJson(repoRoot, tags) {
21357
- const pkgPath = join32(repoRoot, "package.json");
21872
+ const pkgPath = join33(repoRoot, "package.json");
21358
21873
  try {
21359
- if (!existsSync23(pkgPath))
21874
+ if (!existsSync24(pkgPath))
21360
21875
  return;
21361
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
21876
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
21362
21877
  if (pkg.name && typeof pkg.name === "string") {
21363
21878
  const parts = pkg.name.replace(/^@/, "").split("/");
21364
21879
  for (const p of parts)
@@ -21402,7 +21917,7 @@ function extractFromManifests(repoRoot, tags) {
21402
21917
  { file: ".github/workflows", tag: "ci/cd" }
21403
21918
  ];
21404
21919
  for (const check of manifestChecks) {
21405
- if (existsSync23(join32(repoRoot, check.file))) {
21920
+ if (existsSync24(join33(repoRoot, check.file))) {
21406
21921
  tags.push(check.tag);
21407
21922
  }
21408
21923
  }
@@ -21424,16 +21939,16 @@ function extractFromSessions(repoRoot, tags) {
21424
21939
  }
21425
21940
  }
21426
21941
  function extractFromMemory(repoRoot, tags) {
21427
- const memoryDir = join32(repoRoot, OA_DIR, "memory");
21942
+ const memoryDir = join33(repoRoot, OA_DIR, "memory");
21428
21943
  try {
21429
- if (!existsSync23(memoryDir))
21944
+ if (!existsSync24(memoryDir))
21430
21945
  return;
21431
21946
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
21432
21947
  for (const file of files) {
21433
21948
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
21434
21949
  tags.push(topic);
21435
21950
  try {
21436
- const data = JSON.parse(readFileSync16(join32(memoryDir, file), "utf-8"));
21951
+ const data = JSON.parse(readFileSync17(join33(memoryDir, file), "utf-8"));
21437
21952
  if (data && typeof data === "object") {
21438
21953
  const keys = Object.keys(data).slice(0, 3);
21439
21954
  for (const key of keys) {
@@ -21568,25 +22083,25 @@ var init_carousel_descriptors = __esm({
21568
22083
  });
21569
22084
 
21570
22085
  // packages/cli/dist/tui/voice.js
21571
- import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync17, unlinkSync as unlinkSync4 } from "node:fs";
21572
- import { join as join33 } from "node:path";
22086
+ import { existsSync as existsSync25, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10, readFileSync as readFileSync18, unlinkSync as unlinkSync4 } from "node:fs";
22087
+ import { join as join34 } from "node:path";
21573
22088
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
21574
- import { execSync as execSync20, spawn as nodeSpawn } from "node:child_process";
22089
+ import { execSync as execSync21, spawn as nodeSpawn } from "node:child_process";
21575
22090
  import { createRequire } from "node:module";
21576
22091
  function voiceDir() {
21577
- return join33(homedir12(), ".open-agents", "voice");
22092
+ return join34(homedir12(), ".open-agents", "voice");
21578
22093
  }
21579
22094
  function modelsDir() {
21580
- return join33(voiceDir(), "models");
22095
+ return join34(voiceDir(), "models");
21581
22096
  }
21582
22097
  function modelDir(id) {
21583
- return join33(modelsDir(), id);
22098
+ return join34(modelsDir(), id);
21584
22099
  }
21585
22100
  function modelOnnxPath(id) {
21586
- return join33(modelDir(id), "model.onnx");
22101
+ return join34(modelDir(id), "model.onnx");
21587
22102
  }
21588
22103
  function modelConfigPath(id) {
21589
- return join33(modelDir(id), "config.json");
22104
+ return join34(modelDir(id), "config.json");
21590
22105
  }
21591
22106
  function describeToolCall(toolName, args, personality = 2) {
21592
22107
  const path = args["path"];
@@ -22032,7 +22547,7 @@ var init_voice = __esm({
22032
22547
  const audioData = result["output"].data;
22033
22548
  if (audioData.length === 0)
22034
22549
  return;
22035
- const wavPath = join33(tmpdir6(), `oa-voice-${Date.now()}.wav`);
22550
+ const wavPath = join34(tmpdir6(), `oa-voice-${Date.now()}.wav`);
22036
22551
  this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
22037
22552
  await this.playWav(wavPath);
22038
22553
  try {
@@ -22112,7 +22627,7 @@ var init_voice = __esm({
22112
22627
  buffer.write("data", 36);
22113
22628
  buffer.writeUInt32LE(dataSize, 40);
22114
22629
  Buffer.from(int16.buffer, int16.byteOffset, int16.byteLength).copy(buffer, 44);
22115
- writeFileSync9(path, buffer);
22630
+ writeFileSync10(path, buffer);
22116
22631
  }
22117
22632
  // -------------------------------------------------------------------------
22118
22633
  // Audio playback (system default speakers)
@@ -22121,7 +22636,7 @@ var init_voice = __esm({
22121
22636
  const cmd = this.getPlayCommand(path);
22122
22637
  if (!cmd)
22123
22638
  return;
22124
- return new Promise((resolve26) => {
22639
+ return new Promise((resolve27) => {
22125
22640
  const child = nodeSpawn(cmd[0], cmd.slice(1), {
22126
22641
  stdio: "ignore",
22127
22642
  detached: false
@@ -22130,12 +22645,12 @@ var init_voice = __esm({
22130
22645
  child.on("close", () => {
22131
22646
  if (this.currentPlayback === child)
22132
22647
  this.currentPlayback = null;
22133
- resolve26();
22648
+ resolve27();
22134
22649
  });
22135
22650
  child.on("error", () => {
22136
22651
  if (this.currentPlayback === child)
22137
22652
  this.currentPlayback = null;
22138
- resolve26();
22653
+ resolve27();
22139
22654
  });
22140
22655
  setTimeout(() => {
22141
22656
  if (this.currentPlayback === child) {
@@ -22145,7 +22660,7 @@ var init_voice = __esm({
22145
22660
  }
22146
22661
  this.currentPlayback = null;
22147
22662
  }
22148
- resolve26();
22663
+ resolve27();
22149
22664
  }, 15e3);
22150
22665
  });
22151
22666
  }
@@ -22162,7 +22677,7 @@ var init_voice = __esm({
22162
22677
  }
22163
22678
  for (const player of ["paplay", "pw-play", "aplay"]) {
22164
22679
  try {
22165
- execSync20(`which ${player}`, { stdio: "pipe" });
22680
+ execSync21(`which ${player}`, { stdio: "pipe" });
22166
22681
  return [player, path];
22167
22682
  } catch {
22168
22683
  }
@@ -22186,30 +22701,30 @@ var init_voice = __esm({
22186
22701
  return;
22187
22702
  const arch = process.arch;
22188
22703
  const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
22189
- mkdirSync9(voiceDir(), { recursive: true });
22190
- const pkgPath = join33(voiceDir(), "package.json");
22704
+ mkdirSync10(voiceDir(), { recursive: true });
22705
+ const pkgPath = join34(voiceDir(), "package.json");
22191
22706
  const expectedDeps = {
22192
22707
  "onnxruntime-node": "^1.21.0",
22193
22708
  "phonemizer": "^1.2.1"
22194
22709
  };
22195
- if (existsSync24(pkgPath)) {
22710
+ if (existsSync25(pkgPath)) {
22196
22711
  try {
22197
- const existing = JSON.parse(readFileSync17(pkgPath, "utf8"));
22712
+ const existing = JSON.parse(readFileSync18(pkgPath, "utf8"));
22198
22713
  if (!existing.dependencies?.["phonemizer"]) {
22199
22714
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
22200
- writeFileSync9(pkgPath, JSON.stringify(existing, null, 2));
22715
+ writeFileSync10(pkgPath, JSON.stringify(existing, null, 2));
22201
22716
  }
22202
22717
  } catch {
22203
22718
  }
22204
22719
  }
22205
- if (!existsSync24(pkgPath)) {
22206
- writeFileSync9(pkgPath, JSON.stringify({
22720
+ if (!existsSync25(pkgPath)) {
22721
+ writeFileSync10(pkgPath, JSON.stringify({
22207
22722
  name: "open-agents-voice",
22208
22723
  private: true,
22209
22724
  dependencies: expectedDeps
22210
22725
  }, null, 2));
22211
22726
  }
22212
- const voiceRequire = createRequire(join33(voiceDir(), "index.js"));
22727
+ const voiceRequire = createRequire(join34(voiceDir(), "index.js"));
22213
22728
  try {
22214
22729
  this.ort = voiceRequire("onnxruntime-node");
22215
22730
  } catch {
@@ -22218,7 +22733,7 @@ var init_voice = __esm({
22218
22733
  }
22219
22734
  renderInfo("Installing ONNX runtime for voice synthesis...");
22220
22735
  try {
22221
- execSync20("npm install --no-audit --no-fund", {
22736
+ execSync21("npm install --no-audit --no-fund", {
22222
22737
  cwd: voiceDir(),
22223
22738
  stdio: "pipe",
22224
22739
  timeout: 12e4
@@ -22239,7 +22754,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
22239
22754
  }
22240
22755
  renderInfo("Installing phonemizer for voice synthesis...");
22241
22756
  try {
22242
- execSync20("npm install --no-audit --no-fund", {
22757
+ execSync21("npm install --no-audit --no-fund", {
22243
22758
  cwd: voiceDir(),
22244
22759
  stdio: "pipe",
22245
22760
  timeout: 12e4
@@ -22263,18 +22778,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
22263
22778
  const dir = modelDir(id);
22264
22779
  const onnxPath = modelOnnxPath(id);
22265
22780
  const configPath = modelConfigPath(id);
22266
- if (existsSync24(onnxPath) && existsSync24(configPath))
22781
+ if (existsSync25(onnxPath) && existsSync25(configPath))
22267
22782
  return;
22268
- mkdirSync9(dir, { recursive: true });
22269
- if (!existsSync24(configPath)) {
22783
+ mkdirSync10(dir, { recursive: true });
22784
+ if (!existsSync25(configPath)) {
22270
22785
  renderInfo(`Downloading ${model.label} voice config...`);
22271
22786
  const configResp = await fetch(model.configUrl);
22272
22787
  if (!configResp.ok)
22273
22788
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
22274
22789
  const configText = await configResp.text();
22275
- writeFileSync9(configPath, configText);
22790
+ writeFileSync10(configPath, configText);
22276
22791
  }
22277
- if (!existsSync24(onnxPath)) {
22792
+ if (!existsSync25(onnxPath)) {
22278
22793
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
22279
22794
  const onnxResp = await fetch(model.onnxUrl);
22280
22795
  if (!onnxResp.ok)
@@ -22298,7 +22813,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
22298
22813
  }
22299
22814
  process.stdout.write("\r" + " ".repeat(60) + "\r");
22300
22815
  const fullBuffer = Buffer.concat(chunks);
22301
- writeFileSync9(onnxPath, fullBuffer);
22816
+ writeFileSync10(onnxPath, fullBuffer);
22302
22817
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
22303
22818
  }
22304
22819
  }
@@ -22310,10 +22825,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
22310
22825
  throw new Error("ONNX runtime not loaded");
22311
22826
  const onnxPath = modelOnnxPath(this.modelId);
22312
22827
  const configPath = modelConfigPath(this.modelId);
22313
- if (!existsSync24(onnxPath) || !existsSync24(configPath)) {
22828
+ if (!existsSync25(onnxPath) || !existsSync25(configPath)) {
22314
22829
  throw new Error(`Model files not found for ${this.modelId}`);
22315
22830
  }
22316
- this.config = JSON.parse(readFileSync17(configPath, "utf8"));
22831
+ this.config = JSON.parse(readFileSync18(configPath, "utf8"));
22317
22832
  renderInfo("Loading voice model...");
22318
22833
  this.session = await this.ort.InferenceSession.create(onnxPath, {
22319
22834
  executionProviders: ["cpu"],
@@ -22813,13 +23328,13 @@ var init_stream_renderer = __esm({
22813
23328
  });
22814
23329
 
22815
23330
  // packages/cli/dist/tui/edit-history.js
22816
- import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
22817
- import { join as join34 } from "node:path";
23331
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync11 } from "node:fs";
23332
+ import { join as join35 } from "node:path";
22818
23333
  function createEditHistoryLogger(repoRoot, sessionId) {
22819
- const historyDir = join34(repoRoot, ".oa", "history");
22820
- const logPath = join34(historyDir, "edits.jsonl");
23334
+ const historyDir = join35(repoRoot, ".oa", "history");
23335
+ const logPath = join35(historyDir, "edits.jsonl");
22821
23336
  try {
22822
- mkdirSync10(historyDir, { recursive: true });
23337
+ mkdirSync11(historyDir, { recursive: true });
22823
23338
  } catch {
22824
23339
  }
22825
23340
  function logToolCall(toolName, toolArgs, success) {
@@ -22835,7 +23350,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
22835
23350
  args: sanitizeArgs(toolName, toolArgs)
22836
23351
  };
22837
23352
  try {
22838
- appendFileSync(logPath, JSON.stringify(entry) + "\n", "utf-8");
23353
+ appendFileSync2(logPath, JSON.stringify(entry) + "\n", "utf-8");
22839
23354
  } catch {
22840
23355
  }
22841
23356
  }
@@ -22928,9 +23443,9 @@ var init_edit_history = __esm({
22928
23443
  });
22929
23444
 
22930
23445
  // packages/cli/dist/tui/dream-engine.js
22931
- import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync18, existsSync as existsSync25, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
22932
- import { join as join35, basename as basename12 } from "node:path";
22933
- import { execSync as execSync21 } from "node:child_process";
23446
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11, readFileSync as readFileSync19, existsSync as existsSync26, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
23447
+ import { join as join36, basename as basename12 } from "node:path";
23448
+ import { execSync as execSync22 } from "node:child_process";
22934
23449
  function adaptTool(tool) {
22935
23450
  return {
22936
23451
  name: tool.name,
@@ -23104,14 +23619,14 @@ var init_dream_engine = __esm({
23104
23619
  const content = String(args["content"] ?? "");
23105
23620
  if (!rawPath)
23106
23621
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
23107
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join35(this.dreamsDir, basename12(rawPath)) : join35(this.dreamsDir, rawPath);
23622
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join36(this.dreamsDir, basename12(rawPath)) : join36(this.dreamsDir, rawPath);
23108
23623
  if (!targetPath.startsWith(this.dreamsDir)) {
23109
23624
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
23110
23625
  }
23111
23626
  try {
23112
- const dir = join35(targetPath, "..");
23113
- mkdirSync11(dir, { recursive: true });
23114
- writeFileSync10(targetPath, content, "utf-8");
23627
+ const dir = join36(targetPath, "..");
23628
+ mkdirSync12(dir, { recursive: true });
23629
+ writeFileSync11(targetPath, content, "utf-8");
23115
23630
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
23116
23631
  } catch (err) {
23117
23632
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -23139,20 +23654,20 @@ var init_dream_engine = __esm({
23139
23654
  const rawPath = String(args["path"] ?? "");
23140
23655
  const oldStr = String(args["old_string"] ?? "");
23141
23656
  const newStr = String(args["new_string"] ?? "");
23142
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join35(this.dreamsDir, basename12(rawPath)) : join35(this.dreamsDir, rawPath);
23657
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join36(this.dreamsDir, basename12(rawPath)) : join36(this.dreamsDir, rawPath);
23143
23658
  if (!targetPath.startsWith(this.dreamsDir)) {
23144
23659
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
23145
23660
  }
23146
23661
  try {
23147
- if (!existsSync25(targetPath)) {
23662
+ if (!existsSync26(targetPath)) {
23148
23663
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
23149
23664
  }
23150
- let content = readFileSync18(targetPath, "utf-8");
23665
+ let content = readFileSync19(targetPath, "utf-8");
23151
23666
  if (!content.includes(oldStr)) {
23152
23667
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
23153
23668
  }
23154
23669
  content = content.replace(oldStr, newStr);
23155
- writeFileSync10(targetPath, content, "utf-8");
23670
+ writeFileSync11(targetPath, content, "utf-8");
23156
23671
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
23157
23672
  } catch (err) {
23158
23673
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -23183,7 +23698,7 @@ var init_dream_engine = __esm({
23183
23698
  }
23184
23699
  }
23185
23700
  try {
23186
- const output = execSync21(cmd, {
23701
+ const output = execSync22(cmd, {
23187
23702
  cwd: this.repoRoot,
23188
23703
  timeout: 3e4,
23189
23704
  encoding: "utf-8",
@@ -23206,7 +23721,7 @@ var init_dream_engine = __esm({
23206
23721
  constructor(config, repoRoot) {
23207
23722
  this.config = config;
23208
23723
  this.repoRoot = repoRoot;
23209
- this.dreamsDir = join35(repoRoot, ".oa", "dreams");
23724
+ this.dreamsDir = join36(repoRoot, ".oa", "dreams");
23210
23725
  this.state = {
23211
23726
  mode: "default",
23212
23727
  active: false,
@@ -23237,7 +23752,7 @@ var init_dream_engine = __esm({
23237
23752
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
23238
23753
  results: []
23239
23754
  };
23240
- mkdirSync11(this.dreamsDir, { recursive: true });
23755
+ mkdirSync12(this.dreamsDir, { recursive: true });
23241
23756
  this.saveDreamState();
23242
23757
  try {
23243
23758
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -23286,8 +23801,8 @@ ${result.summary}`;
23286
23801
  if (mode !== "default" || cycle === totalCycles) {
23287
23802
  renderDreamContraction(cycle);
23288
23803
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
23289
- const summaryPath = join35(this.dreamsDir, `cycle-${cycle}-summary.md`);
23290
- writeFileSync10(summaryPath, cycleSummary, "utf-8");
23804
+ const summaryPath = join36(this.dreamsDir, `cycle-${cycle}-summary.md`);
23805
+ writeFileSync11(summaryPath, cycleSummary, "utf-8");
23291
23806
  }
23292
23807
  if (mode === "lucid" && !this.abortController.signal.aborted) {
23293
23808
  this.saveVersionCheckpoint(cycle);
@@ -23525,29 +24040,29 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
23525
24040
  }
23526
24041
  /** Save workspace backup for lucid mode */
23527
24042
  saveVersionCheckpoint(cycle) {
23528
- const checkpointDir = join35(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
24043
+ const checkpointDir = join36(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
23529
24044
  try {
23530
- mkdirSync11(checkpointDir, { recursive: true });
24045
+ mkdirSync12(checkpointDir, { recursive: true });
23531
24046
  try {
23532
- const gitStatus = execSync21("git status --porcelain", {
24047
+ const gitStatus = execSync22("git status --porcelain", {
23533
24048
  cwd: this.repoRoot,
23534
24049
  encoding: "utf-8",
23535
24050
  timeout: 1e4
23536
24051
  });
23537
- const gitDiff = execSync21("git diff", {
24052
+ const gitDiff = execSync22("git diff", {
23538
24053
  cwd: this.repoRoot,
23539
24054
  encoding: "utf-8",
23540
24055
  timeout: 1e4
23541
24056
  });
23542
- const gitHash = execSync21("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
24057
+ const gitHash = execSync22("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
23543
24058
  cwd: this.repoRoot,
23544
24059
  encoding: "utf-8",
23545
24060
  timeout: 5e3
23546
24061
  }).trim();
23547
- writeFileSync10(join35(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
23548
- writeFileSync10(join35(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
23549
- writeFileSync10(join35(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
23550
- writeFileSync10(join35(checkpointDir, "checkpoint.json"), JSON.stringify({
24062
+ writeFileSync11(join36(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
24063
+ writeFileSync11(join36(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
24064
+ writeFileSync11(join36(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
24065
+ writeFileSync11(join36(checkpointDir, "checkpoint.json"), JSON.stringify({
23551
24066
  cycle,
23552
24067
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
23553
24068
  gitHash,
@@ -23555,7 +24070,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
23555
24070
  }, null, 2), "utf-8");
23556
24071
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
23557
24072
  } catch {
23558
- writeFileSync10(join35(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
24073
+ writeFileSync11(join36(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
23559
24074
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
23560
24075
  }
23561
24076
  } catch (err) {
@@ -23613,14 +24128,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
23613
24128
  ---
23614
24129
  *Auto-generated by open-agents dream engine*
23615
24130
  `;
23616
- writeFileSync10(join35(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
24131
+ writeFileSync11(join36(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
23617
24132
  } catch {
23618
24133
  }
23619
24134
  }
23620
24135
  /** Save dream state for resume/inspection */
23621
24136
  saveDreamState() {
23622
24137
  try {
23623
- writeFileSync10(join35(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
24138
+ writeFileSync11(join36(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
23624
24139
  } catch {
23625
24140
  }
23626
24141
  }
@@ -23773,8 +24288,8 @@ var init_bless_engine = __esm({
23773
24288
  });
23774
24289
 
23775
24290
  // packages/cli/dist/tui/dmn-engine.js
23776
- import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
23777
- import { join as join36, basename as basename13 } from "node:path";
24291
+ import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync12, mkdirSync as mkdirSync13, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
24292
+ import { join as join37, basename as basename13 } from "node:path";
23778
24293
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
23779
24294
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
23780
24295
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -24006,9 +24521,9 @@ var init_dmn_engine = __esm({
24006
24521
  constructor(config, repoRoot) {
24007
24522
  this.config = config;
24008
24523
  this.repoRoot = repoRoot;
24009
- this.stateDir = join36(repoRoot, ".oa", "dmn");
24010
- this.historyDir = join36(repoRoot, ".oa", "dmn", "cycles");
24011
- mkdirSync12(this.historyDir, { recursive: true });
24524
+ this.stateDir = join37(repoRoot, ".oa", "dmn");
24525
+ this.historyDir = join37(repoRoot, ".oa", "dmn", "cycles");
24526
+ mkdirSync13(this.historyDir, { recursive: true });
24012
24527
  this.loadState();
24013
24528
  }
24014
24529
  get stats() {
@@ -24596,11 +25111,11 @@ OUTPUT: Call task_complete with JSON:
24596
25111
  async gatherMemoryTopics() {
24597
25112
  const topics = [];
24598
25113
  const dirs = [
24599
- join36(this.repoRoot, ".oa", "memory"),
24600
- join36(this.repoRoot, ".open-agents", "memory")
25114
+ join37(this.repoRoot, ".oa", "memory"),
25115
+ join37(this.repoRoot, ".open-agents", "memory")
24601
25116
  ];
24602
25117
  for (const dir of dirs) {
24603
- if (!existsSync26(dir))
25118
+ if (!existsSync27(dir))
24604
25119
  continue;
24605
25120
  try {
24606
25121
  const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
@@ -24616,29 +25131,29 @@ OUTPUT: Call task_complete with JSON:
24616
25131
  }
24617
25132
  // ── State persistence ─────────────────────────────────────────────────
24618
25133
  loadState() {
24619
- const path = join36(this.stateDir, "state.json");
24620
- if (existsSync26(path)) {
25134
+ const path = join37(this.stateDir, "state.json");
25135
+ if (existsSync27(path)) {
24621
25136
  try {
24622
- this.state = JSON.parse(readFileSync19(path, "utf-8"));
25137
+ this.state = JSON.parse(readFileSync20(path, "utf-8"));
24623
25138
  } catch {
24624
25139
  }
24625
25140
  }
24626
25141
  }
24627
25142
  saveState() {
24628
25143
  try {
24629
- writeFileSync11(join36(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
25144
+ writeFileSync12(join37(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
24630
25145
  } catch {
24631
25146
  }
24632
25147
  }
24633
25148
  saveCycleResult(result) {
24634
25149
  try {
24635
25150
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
24636
- writeFileSync11(join36(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
25151
+ writeFileSync12(join37(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
24637
25152
  const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
24638
25153
  if (files.length > 50) {
24639
25154
  for (const old of files.slice(0, files.length - 50)) {
24640
25155
  try {
24641
- unlinkSync5(join36(this.historyDir, old));
25156
+ unlinkSync5(join37(this.historyDir, old));
24642
25157
  } catch {
24643
25158
  }
24644
25159
  }
@@ -24651,8 +25166,8 @@ OUTPUT: Call task_complete with JSON:
24651
25166
  });
24652
25167
 
24653
25168
  // packages/cli/dist/tui/snr-engine.js
24654
- import { existsSync as existsSync27, readdirSync as readdirSync12, readFileSync as readFileSync20 } from "node:fs";
24655
- import { join as join37, basename as basename14 } from "node:path";
25169
+ import { existsSync as existsSync28, readdirSync as readdirSync12, readFileSync as readFileSync21 } from "node:fs";
25170
+ import { join as join38, basename as basename14 } from "node:path";
24656
25171
  function computeDPrime(signalScores, noiseScores) {
24657
25172
  if (signalScores.length === 0 || noiseScores.length === 0)
24658
25173
  return 0;
@@ -24899,11 +25414,11 @@ Call task_complete with the JSON array when done.`, onEvent)
24899
25414
  loadMemoryEntries(topics) {
24900
25415
  const entries = [];
24901
25416
  const dirs = [
24902
- join37(this.repoRoot, ".oa", "memory"),
24903
- join37(this.repoRoot, ".open-agents", "memory")
25417
+ join38(this.repoRoot, ".oa", "memory"),
25418
+ join38(this.repoRoot, ".open-agents", "memory")
24904
25419
  ];
24905
25420
  for (const dir of dirs) {
24906
- if (!existsSync27(dir))
25421
+ if (!existsSync28(dir))
24907
25422
  continue;
24908
25423
  try {
24909
25424
  const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
@@ -24912,7 +25427,7 @@ Call task_complete with the JSON array when done.`, onEvent)
24912
25427
  if (topics.length > 0 && !topics.includes(topic))
24913
25428
  continue;
24914
25429
  try {
24915
- const data = JSON.parse(readFileSync20(join37(dir, f), "utf-8"));
25430
+ const data = JSON.parse(readFileSync21(join38(dir, f), "utf-8"));
24916
25431
  for (const [key, val] of Object.entries(data)) {
24917
25432
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
24918
25433
  entries.push({ topic, key, value });
@@ -26309,11 +26824,11 @@ var init_status_bar = __esm({
26309
26824
  import * as readline2 from "node:readline";
26310
26825
  import { Writable } from "node:stream";
26311
26826
  import { cwd } from "node:process";
26312
- import { resolve as resolve23, join as join38, dirname as dirname11, extname as extname9 } from "node:path";
26827
+ import { resolve as resolve24, join as join39, dirname as dirname12, extname as extname9 } from "node:path";
26313
26828
  import { createRequire as createRequire2 } from "node:module";
26314
- import { fileURLToPath as fileURLToPath8 } from "node:url";
26315
- import { readFileSync as readFileSync21, rmSync as rmSync2, readdirSync as readdirSync13 } from "node:fs";
26316
- import { existsSync as existsSync28 } from "node:fs";
26829
+ import { fileURLToPath as fileURLToPath9 } from "node:url";
26830
+ import { readFileSync as readFileSync22, rmSync as rmSync2, readdirSync as readdirSync13 } from "node:fs";
26831
+ import { existsSync as existsSync29 } from "node:fs";
26317
26832
  function formatTimeAgo(date) {
26318
26833
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
26319
26834
  if (seconds < 60)
@@ -26330,14 +26845,14 @@ function formatTimeAgo(date) {
26330
26845
  function getVersion() {
26331
26846
  try {
26332
26847
  const require2 = createRequire2(import.meta.url);
26333
- const thisDir = dirname11(fileURLToPath8(import.meta.url));
26848
+ const thisDir = dirname12(fileURLToPath9(import.meta.url));
26334
26849
  const candidates = [
26335
- join38(thisDir, "..", "package.json"),
26336
- join38(thisDir, "..", "..", "package.json"),
26337
- join38(thisDir, "..", "..", "..", "package.json")
26850
+ join39(thisDir, "..", "package.json"),
26851
+ join39(thisDir, "..", "..", "package.json"),
26852
+ join39(thisDir, "..", "..", "..", "package.json")
26338
26853
  ];
26339
26854
  for (const pkgPath of candidates) {
26340
- if (existsSync28(pkgPath)) {
26855
+ if (existsSync29(pkgPath)) {
26341
26856
  const pkg = require2(pkgPath);
26342
26857
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
26343
26858
  return pkg.version ?? "0.0.0";
@@ -26438,6 +26953,8 @@ function buildTools(repoRoot, config, contextWindowSize) {
26438
26953
  new OcrImageAdvancedTool(repoRoot),
26439
26954
  // Browser automation (headless Chrome via Hydra scrape service)
26440
26955
  new BrowserActionTool(),
26956
+ // Autoresearch (autonomous ML experiment loop)
26957
+ new AutoresearchTool(repoRoot),
26441
26958
  // Temporal agency (scheduling, reminders, attention steering)
26442
26959
  new SchedulerTool(repoRoot),
26443
26960
  new ReminderTool(repoRoot),
@@ -26529,15 +27046,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
26529
27046
  function gatherMemorySnippets(root) {
26530
27047
  const snippets = [];
26531
27048
  const dirs = [
26532
- join38(root, ".oa", "memory"),
26533
- join38(root, ".open-agents", "memory")
27049
+ join39(root, ".oa", "memory"),
27050
+ join39(root, ".open-agents", "memory")
26534
27051
  ];
26535
27052
  for (const dir of dirs) {
26536
- if (!existsSync28(dir))
27053
+ if (!existsSync29(dir))
26537
27054
  continue;
26538
27055
  try {
26539
27056
  for (const f of readdirSync13(dir).filter((f2) => f2.endsWith(".json"))) {
26540
- const data = JSON.parse(readFileSync21(join38(dir, f), "utf-8"));
27057
+ const data = JSON.parse(readFileSync22(join39(dir, f), "utf-8"));
26541
27058
  for (const val of Object.values(data)) {
26542
27059
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
26543
27060
  if (v.length > 10)
@@ -26937,7 +27454,7 @@ ${entry.fullContent}`
26937
27454
  } };
26938
27455
  }
26939
27456
  async function startInteractive(config, repoPath) {
26940
- const repoRoot = resolve23(repoPath ?? cwd());
27457
+ const repoRoot = resolve24(repoPath ?? cwd());
26941
27458
  const resumeFlag = process.env.__OA_RESUMED ?? "";
26942
27459
  const isResumed = resumeFlag !== "";
26943
27460
  const hasTaskToResume = resumeFlag === "1";
@@ -27091,14 +27608,14 @@ async function startInteractive(config, repoPath) {
27091
27608
  renderInfo(msg);
27092
27609
  statusBar.endContentWrite();
27093
27610
  }
27094
- }, () => new Promise((resolve26) => {
27611
+ }, () => new Promise((resolve27) => {
27095
27612
  depSudoPromptPending = true;
27096
27613
  depSudoResolver = (pw) => {
27097
27614
  depSudoPromptPending = false;
27098
27615
  depSudoResolver = null;
27099
27616
  if (pw)
27100
27617
  sessionSudoPassword = pw;
27101
- resolve26(pw);
27618
+ resolve27(pw);
27102
27619
  };
27103
27620
  if (statusBar?.isActive) {
27104
27621
  statusBar.beginContentWrite();
@@ -27723,8 +28240,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
27723
28240
  return true;
27724
28241
  },
27725
28242
  destroyProject() {
27726
- const oaPath = join38(repoRoot, OA_DIR);
27727
- if (existsSync28(oaPath)) {
28243
+ const oaPath = join39(repoRoot, OA_DIR);
28244
+ if (existsSync29(oaPath)) {
27728
28245
  try {
27729
28246
  rmSync2(oaPath, { recursive: true, force: true });
27730
28247
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -27998,13 +28515,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
27998
28515
  }
27999
28516
  }
28000
28517
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
28001
- const isImage = isImagePath(cleanPath) && existsSync28(resolve23(repoRoot, cleanPath));
28002
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync28(resolve23(repoRoot, cleanPath));
28518
+ const isImage = isImagePath(cleanPath) && existsSync29(resolve24(repoRoot, cleanPath));
28519
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync29(resolve24(repoRoot, cleanPath));
28003
28520
  if (activeTask) {
28004
28521
  if (isImage) {
28005
28522
  try {
28006
- const imgPath = resolve23(repoRoot, cleanPath);
28007
- const imgBuffer = readFileSync21(imgPath);
28523
+ const imgPath = resolve24(repoRoot, cleanPath);
28524
+ const imgBuffer = readFileSync22(imgPath);
28008
28525
  const base64 = imgBuffer.toString("base64");
28009
28526
  const ext = extname9(cleanPath).toLowerCase();
28010
28527
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -28017,7 +28534,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
28017
28534
  } else if (isMedia) {
28018
28535
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
28019
28536
  const engine = getListenEngine();
28020
- const result = await engine.transcribeFile(resolve23(repoRoot, cleanPath), repoRoot);
28537
+ const result = await engine.transcribeFile(resolve24(repoRoot, cleanPath), repoRoot);
28021
28538
  if (result) {
28022
28539
  const transcript = `[Transcription of ${cleanPath}]
28023
28540
  ${result.text}`;
@@ -28050,7 +28567,7 @@ ${result.text}`;
28050
28567
  if (isMedia && fullInput === input) {
28051
28568
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
28052
28569
  const engine = getListenEngine();
28053
- const result = await engine.transcribeFile(resolve23(repoRoot, cleanPath), repoRoot);
28570
+ const result = await engine.transcribeFile(resolve24(repoRoot, cleanPath), repoRoot);
28054
28571
  if (result) {
28055
28572
  fullInput = `The user has provided an audio/video file: ${cleanPath}.
28056
28573
 
@@ -28268,7 +28785,7 @@ ${c2.dim("(Use /quit to exit)")}
28268
28785
  });
28269
28786
  }
28270
28787
  async function runWithTUI(task, config, repoPath) {
28271
- const repoRoot = resolve23(repoPath ?? cwd());
28788
+ const repoRoot = resolve24(repoPath ?? cwd());
28272
28789
  const needsSetup = isFirstRun() || !await isModelAvailable(config);
28273
28790
  if (needsSetup && config.backendType === "ollama") {
28274
28791
  const setupModel = await runSetupWizard(config);
@@ -28378,7 +28895,7 @@ import { glob } from "glob";
28378
28895
  import ignore from "ignore";
28379
28896
  import { readFile as readFile14, stat as stat4 } from "node:fs/promises";
28380
28897
  import { createHash } from "node:crypto";
28381
- import { join as join39, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
28898
+ import { join as join40, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
28382
28899
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
28383
28900
  var init_codebase_indexer = __esm({
28384
28901
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -28422,7 +28939,7 @@ var init_codebase_indexer = __esm({
28422
28939
  const ig = ignore.default();
28423
28940
  if (this.config.respectGitignore) {
28424
28941
  try {
28425
- const gitignoreContent = await readFile14(join39(this.config.rootDir, ".gitignore"), "utf-8");
28942
+ const gitignoreContent = await readFile14(join40(this.config.rootDir, ".gitignore"), "utf-8");
28426
28943
  ig.add(gitignoreContent);
28427
28944
  } catch {
28428
28945
  }
@@ -28437,7 +28954,7 @@ var init_codebase_indexer = __esm({
28437
28954
  for (const relativePath of files) {
28438
28955
  if (ig.ignores(relativePath))
28439
28956
  continue;
28440
- const fullPath = join39(this.config.rootDir, relativePath);
28957
+ const fullPath = join40(this.config.rootDir, relativePath);
28441
28958
  try {
28442
28959
  const fileStat = await stat4(fullPath);
28443
28960
  if (fileStat.size > this.config.maxFileSize)
@@ -28483,7 +29000,7 @@ var init_codebase_indexer = __esm({
28483
29000
  if (!child) {
28484
29001
  child = {
28485
29002
  name: part,
28486
- path: join39(current.path, part),
29003
+ path: join40(current.path, part),
28487
29004
  type: "directory",
28488
29005
  children: []
28489
29006
  };
@@ -28565,14 +29082,14 @@ var index_repo_exports = {};
28565
29082
  __export(index_repo_exports, {
28566
29083
  indexRepoCommand: () => indexRepoCommand
28567
29084
  });
28568
- import { resolve as resolve24 } from "node:path";
28569
- import { existsSync as existsSync29, statSync as statSync10 } from "node:fs";
29085
+ import { resolve as resolve25 } from "node:path";
29086
+ import { existsSync as existsSync30, statSync as statSync10 } from "node:fs";
28570
29087
  import { cwd as cwd2 } from "node:process";
28571
29088
  async function indexRepoCommand(opts, _config) {
28572
- const repoRoot = resolve24(opts.repoPath ?? cwd2());
29089
+ const repoRoot = resolve25(opts.repoPath ?? cwd2());
28573
29090
  printHeader("Index Repository");
28574
29091
  printInfo(`Indexing: ${repoRoot}`);
28575
- if (!existsSync29(repoRoot)) {
29092
+ if (!existsSync30(repoRoot)) {
28576
29093
  printError(`Path does not exist: ${repoRoot}`);
28577
29094
  process.exit(1);
28578
29095
  }
@@ -28824,7 +29341,7 @@ var config_exports = {};
28824
29341
  __export(config_exports, {
28825
29342
  configCommand: () => configCommand
28826
29343
  });
28827
- import { join as join40, resolve as resolve25 } from "node:path";
29344
+ import { join as join41, resolve as resolve26 } from "node:path";
28828
29345
  import { homedir as homedir13 } from "node:os";
28829
29346
  import { cwd as cwd3 } from "node:process";
28830
29347
  function redactIfSensitive(key, value) {
@@ -28851,7 +29368,7 @@ async function configCommand(opts, config) {
28851
29368
  return handleShow(opts, config);
28852
29369
  }
28853
29370
  function handleShow(opts, config) {
28854
- const repoRoot = resolve25(opts.repoPath ?? cwd3());
29371
+ const repoRoot = resolve26(opts.repoPath ?? cwd3());
28855
29372
  printHeader("Configuration");
28856
29373
  printSection("Active Settings (merged)");
28857
29374
  printKeyValue("backendUrl", config.backendUrl, 2);
@@ -28883,7 +29400,7 @@ function handleShow(opts, config) {
28883
29400
  }
28884
29401
  }
28885
29402
  printSection("Config File");
28886
- printInfo(`~/.open-agents/config.json (${join40(homedir13(), ".open-agents", "config.json")})`);
29403
+ printInfo(`~/.open-agents/config.json (${join41(homedir13(), ".open-agents", "config.json")})`);
28887
29404
  printSection("Priority Chain");
28888
29405
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
28889
29406
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -28916,13 +29433,13 @@ function handleSet(opts, _config) {
28916
29433
  process.exit(1);
28917
29434
  }
28918
29435
  if (opts.local) {
28919
- const repoRoot = resolve25(opts.repoPath ?? cwd3());
29436
+ const repoRoot = resolve26(opts.repoPath ?? cwd3());
28920
29437
  try {
28921
29438
  initOaDirectory(repoRoot);
28922
29439
  const coerced = coerceForSettings(key, value);
28923
29440
  saveProjectSettings(repoRoot, { [key]: coerced });
28924
29441
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
28925
- printInfo(`Saved to ${join40(repoRoot, ".oa", "settings.json")}`);
29442
+ printInfo(`Saved to ${join41(repoRoot, ".oa", "settings.json")}`);
28926
29443
  printInfo("This override applies only when running in this workspace.");
28927
29444
  } catch (err) {
28928
29445
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -28983,7 +29500,7 @@ var serve_exports = {};
28983
29500
  __export(serve_exports, {
28984
29501
  serveCommand: () => serveCommand
28985
29502
  });
28986
- import { spawn as spawn10 } from "node:child_process";
29503
+ import { spawn as spawn11 } from "node:child_process";
28987
29504
  async function serveCommand(opts, config) {
28988
29505
  const backendType = config.backendType;
28989
29506
  if (backendType === "ollama") {
@@ -29075,8 +29592,8 @@ async function serveVllm(opts, config) {
29075
29592
  await runVllmServer(args, opts.verbose ?? false);
29076
29593
  }
29077
29594
  async function runVllmServer(args, verbose) {
29078
- return new Promise((resolve26, reject) => {
29079
- const child = spawn10("python", args, {
29595
+ return new Promise((resolve27, reject) => {
29596
+ const child = spawn11("python", args, {
29080
29597
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
29081
29598
  env: { ...process.env }
29082
29599
  });
@@ -29110,10 +29627,10 @@ async function runVllmServer(args, verbose) {
29110
29627
  child.once("exit", (code, signal) => {
29111
29628
  if (signal) {
29112
29629
  printInfo(`vLLM server stopped by signal ${signal}`);
29113
- resolve26();
29630
+ resolve27();
29114
29631
  } else if (code === 0) {
29115
29632
  printSuccess("vLLM server exited cleanly");
29116
- resolve26();
29633
+ resolve27();
29117
29634
  } else {
29118
29635
  printError(`vLLM server exited with code ${code}`);
29119
29636
  reject(new Error(`vLLM exited with code ${code}`));
@@ -29141,8 +29658,8 @@ __export(eval_exports, {
29141
29658
  evalCommand: () => evalCommand
29142
29659
  });
29143
29660
  import { tmpdir as tmpdir7 } from "node:os";
29144
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12 } from "node:fs";
29145
- import { join as join41 } from "node:path";
29661
+ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13 } from "node:fs";
29662
+ import { join as join42 } from "node:path";
29146
29663
  async function evalCommand(opts, config) {
29147
29664
  const suiteName = opts.suite ?? "basic";
29148
29665
  const suite = SUITES[suiteName];
@@ -29263,9 +29780,9 @@ async function evalCommand(opts, config) {
29263
29780
  process.exit(failed > 0 ? 1 : 0);
29264
29781
  }
29265
29782
  function createTempEvalRepo() {
29266
- const dir = join41(tmpdir7(), `open-agents-eval-${Date.now()}`);
29267
- mkdirSync13(dir, { recursive: true });
29268
- writeFileSync12(join41(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
29783
+ const dir = join42(tmpdir7(), `open-agents-eval-${Date.now()}`);
29784
+ mkdirSync14(dir, { recursive: true });
29785
+ writeFileSync13(join42(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
29269
29786
  return dir;
29270
29787
  }
29271
29788
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -29324,8 +29841,8 @@ init_output();
29324
29841
  init_updater();
29325
29842
  import { parseArgs as nodeParseArgs2 } from "node:util";
29326
29843
  import { createRequire as createRequire3 } from "node:module";
29327
- import { fileURLToPath as fileURLToPath9 } from "node:url";
29328
- import { dirname as dirname12, join as join42 } from "node:path";
29844
+ import { fileURLToPath as fileURLToPath10 } from "node:url";
29845
+ import { dirname as dirname13, join as join43 } from "node:path";
29329
29846
 
29330
29847
  // packages/cli/dist/cli.js
29331
29848
  import { createInterface } from "node:readline";
@@ -29432,7 +29949,7 @@ init_output();
29432
29949
  function getVersion2() {
29433
29950
  try {
29434
29951
  const require2 = createRequire3(import.meta.url);
29435
- const pkgPath = join42(dirname12(fileURLToPath9(import.meta.url)), "..", "package.json");
29952
+ const pkgPath = join43(dirname13(fileURLToPath10(import.meta.url)), "..", "package.json");
29436
29953
  const pkg = require2(pkgPath);
29437
29954
  return pkg.version;
29438
29955
  } catch {