open-agents-ai 0.97.0 → 0.100.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
@@ -6047,7 +6047,8 @@ function loadSkillsFromDir(dir, source, out) {
6047
6047
  description: manifestEntry?.description ?? parseDescription(skillMd),
6048
6048
  triggers: manifestEntry?.triggers ?? parseTriggers(skillMd),
6049
6049
  source,
6050
- filePath: skillMd
6050
+ filePath: skillMd,
6051
+ compactionStrategy: parseCompactionStrategy(skillMd)
6051
6052
  };
6052
6053
  out.set(entry, info);
6053
6054
  }
@@ -6134,6 +6135,25 @@ function parseDescription(filePath) {
6134
6135
  }
6135
6136
  return "";
6136
6137
  }
6138
+ function parseCompactionStrategy(filePath) {
6139
+ try {
6140
+ const content = readFileSync8(filePath, "utf-8");
6141
+ if (!content.startsWith("---"))
6142
+ return void 0;
6143
+ const endIdx = content.indexOf("---", 3);
6144
+ if (endIdx === -1)
6145
+ return void 0;
6146
+ const frontmatter = content.slice(3, endIdx);
6147
+ const match = frontmatter.match(/^compaction_strategy:\s*(.+)$/m);
6148
+ if (!match)
6149
+ return void 0;
6150
+ const val = match[1].trim().toLowerCase();
6151
+ const valid = ["default", "aggressive", "decisions", "errors", "summary", "structured"];
6152
+ return valid.includes(val) ? val : void 0;
6153
+ } catch {
6154
+ return void 0;
6155
+ }
6156
+ }
6137
6157
  function parseTriggers(filePath) {
6138
6158
  const triggers = [];
6139
6159
  try {
@@ -6269,10 +6289,12 @@ Did you mean: ${fuzzy.map((s) => s.name).join(", ")}?` : "\nUse skill_list to se
6269
6289
  durationMs: performance.now() - start
6270
6290
  };
6271
6291
  }
6292
+ const compactionHint = skill.compactionStrategy ? `
6293
+ Compaction strategy: ${skill.compactionStrategy}` : "";
6272
6294
  return {
6273
6295
  success: true,
6274
6296
  output: `# Skill: ${skill.name}
6275
- Source: ${skill.source}
6297
+ Source: ${skill.source}${compactionHint}
6276
6298
 
6277
6299
  ${content}`,
6278
6300
  durationMs: performance.now() - start
@@ -6282,9 +6304,254 @@ ${content}`,
6282
6304
  }
6283
6305
  });
6284
6306
 
6307
+ // packages/execution/dist/tools/skill-builder.js
6308
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
6309
+ import { join as join15, dirname as dirname4 } from "node:path";
6310
+ function loadBuilderPrompt(name, vars) {
6311
+ const candidates = [
6312
+ // Dev layout: execution/dist/tools/ → orchestrator/prompts/
6313
+ join15(dirname4(dirname4(dirname4(__dirname))), "orchestrator", "prompts", "skill-builder", name),
6314
+ // Published layout: publish/dist/ → publish/prompts/
6315
+ join15(dirname4(dirname4(__dirname)), "prompts", "skill-builder", name),
6316
+ // Monorepo root fallback
6317
+ join15(dirname4(dirname4(dirname4(dirname4(__dirname)))), "packages", "orchestrator", "prompts", "skill-builder", name)
6318
+ ];
6319
+ let content;
6320
+ for (const p of candidates) {
6321
+ try {
6322
+ content = readFileSync9(p, "utf-8");
6323
+ break;
6324
+ } catch {
6325
+ }
6326
+ }
6327
+ if (!content) {
6328
+ throw new Error(`Skill builder prompt not found: ${name} (searched: ${candidates.join(", ")})`);
6329
+ }
6330
+ if (!vars)
6331
+ return content;
6332
+ return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
6333
+ }
6334
+ function extractJSON(text) {
6335
+ const codeBlockMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
6336
+ if (codeBlockMatch)
6337
+ return codeBlockMatch[1].trim();
6338
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
6339
+ if (jsonMatch)
6340
+ return jsonMatch[0];
6341
+ throw new Error("No JSON found in LLM response");
6342
+ }
6343
+ var SkillBuildTool;
6344
+ var init_skill_builder = __esm({
6345
+ "packages/execution/dist/tools/skill-builder.js"() {
6346
+ "use strict";
6347
+ SkillBuildTool = class {
6348
+ name = "skill_build";
6349
+ description = "Generate a comprehensive SKILL.md from a simple skill request. Takes a natural language description (e.g. 'learn to write pytest fixtures') and expands it into a structured skill definition with triggers, behaviors, verification steps, and compaction hints. The skill is saved to .oa/skills/ for immediate use with skill_execute.";
6350
+ parameters = {
6351
+ type: "object",
6352
+ properties: {
6353
+ skill_request: {
6354
+ type: "string",
6355
+ description: "Natural language description of the skill to build (e.g. 'write Rust unit tests', 'debug Kubernetes pods', 'optimize SQL queries')"
6356
+ },
6357
+ target_dir: {
6358
+ type: "string",
6359
+ description: "Optional: directory to save the skill. Defaults to .oa/skills/ in the project root. Can also be .aiwg/skills/ for AIWG-compatible deployment."
6360
+ },
6361
+ validate: {
6362
+ type: "boolean",
6363
+ description: "Whether to run the validation phase (default: true). Validation scores the generated skill and suggests improvements."
6364
+ }
6365
+ },
6366
+ required: ["skill_request"]
6367
+ };
6368
+ repoRoot;
6369
+ llmCall;
6370
+ constructor(repoRoot, llmCall) {
6371
+ this.repoRoot = repoRoot;
6372
+ this.llmCall = llmCall;
6373
+ }
6374
+ async execute(args) {
6375
+ const start = performance.now();
6376
+ const skillRequest = String(args["skill_request"] ?? "").trim();
6377
+ const targetDir = String(args["target_dir"] ?? join15(this.repoRoot, ".oa", "skills"));
6378
+ const shouldValidate = args["validate"] !== false;
6379
+ if (!skillRequest) {
6380
+ return {
6381
+ success: false,
6382
+ output: "",
6383
+ error: "skill_request is required. Describe the skill you want to build.",
6384
+ durationMs: performance.now() - start
6385
+ };
6386
+ }
6387
+ try {
6388
+ const seed = await this.analyzeSeed(skillRequest);
6389
+ let skillContent = await this.expandSkill(seed);
6390
+ let validationInfo = "";
6391
+ if (shouldValidate) {
6392
+ const validation = await this.validateSkill(skillContent);
6393
+ validationInfo = `
6394
+ Validation: ${validation.pass ? "PASS" : "NEEDS IMPROVEMENT"} (${validation.overall.toFixed(1)}/5.0)`;
6395
+ if (validation.fixes.length > 0) {
6396
+ validationInfo += `
6397
+ Suggestions: ${validation.fixes.join("; ")}`;
6398
+ }
6399
+ if (!validation.pass && validation.fixes.length > 0) {
6400
+ skillContent = await this.refineSkill(skillContent, validation.fixes);
6401
+ validationInfo += "\n Applied refinement pass.";
6402
+ }
6403
+ }
6404
+ const skillDir = join15(targetDir, seed.name);
6405
+ const skillPath = join15(skillDir, "SKILL.md");
6406
+ if (!existsSync12(skillDir)) {
6407
+ mkdirSync4(skillDir, { recursive: true });
6408
+ }
6409
+ writeFileSync4(skillPath, skillContent, "utf-8");
6410
+ const output = [
6411
+ `Skill "${seed.name}" built successfully.`,
6412
+ ` Domain: ${seed.domain}`,
6413
+ ` Scope: ${seed.scope}`,
6414
+ ` Capabilities: ${seed.capabilities.length}`,
6415
+ ` Triggers: ${seed.triggers.length}`,
6416
+ ` Compaction: ${seed.compaction_strategy}`,
6417
+ ` Saved to: ${skillPath}`,
6418
+ validationInfo,
6419
+ "",
6420
+ 'Use `skill_execute` with name "' + seed.name + '" to load the skill.'
6421
+ ].join("\n");
6422
+ return {
6423
+ success: true,
6424
+ output,
6425
+ durationMs: performance.now() - start
6426
+ };
6427
+ } catch (err) {
6428
+ return {
6429
+ success: false,
6430
+ output: "",
6431
+ error: `Skill build failed: ${err instanceof Error ? err.message : String(err)}`,
6432
+ durationMs: performance.now() - start
6433
+ };
6434
+ }
6435
+ }
6436
+ // -------------------------------------------------------------------------
6437
+ // Phase 1: Seed Analysis
6438
+ // -------------------------------------------------------------------------
6439
+ async analyzeSeed(request) {
6440
+ const prompt = loadBuilderPrompt("seed-analysis.md", {
6441
+ skill_request: request
6442
+ });
6443
+ const response = await this.llmCall([
6444
+ { role: "system", content: prompt },
6445
+ { role: "user", content: `Analyze this skill request: "${request}"` }
6446
+ ]);
6447
+ const jsonStr = extractJSON(response);
6448
+ const seed = JSON.parse(jsonStr);
6449
+ if (!seed.name || !seed.description || !seed.capabilities?.length) {
6450
+ throw new Error("Seed analysis produced incomplete result \u2014 missing name, description, or capabilities");
6451
+ }
6452
+ seed.name = seed.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
6453
+ return seed;
6454
+ }
6455
+ // -------------------------------------------------------------------------
6456
+ // Phase 2: Skill Expansion
6457
+ // -------------------------------------------------------------------------
6458
+ async expandSkill(seed) {
6459
+ const prompt = loadBuilderPrompt("skill-expansion.md", {
6460
+ seed_json: JSON.stringify(seed, null, 2)
6461
+ });
6462
+ const response = await this.llmCall([
6463
+ { role: "system", content: prompt },
6464
+ {
6465
+ role: "user",
6466
+ content: `Generate the complete SKILL.md for the "${seed.name}" skill.`
6467
+ }
6468
+ ]);
6469
+ let content = response.trim();
6470
+ if (content.startsWith("```markdown")) {
6471
+ content = content.slice("```markdown".length).trim();
6472
+ } else if (content.startsWith("```")) {
6473
+ content = content.slice(3).trim();
6474
+ }
6475
+ if (content.endsWith("```")) {
6476
+ content = content.slice(0, -3).trim();
6477
+ }
6478
+ if (!content.startsWith("---")) {
6479
+ const frontmatter = [
6480
+ "---",
6481
+ `name: ${seed.name}`,
6482
+ `description: ${seed.description}`,
6483
+ `compaction_strategy: ${seed.compaction_strategy}`,
6484
+ "triggers:",
6485
+ ...seed.triggers.map((t) => ` - "${t}"`),
6486
+ "---",
6487
+ ""
6488
+ ].join("\n");
6489
+ content = frontmatter + content;
6490
+ }
6491
+ return content;
6492
+ }
6493
+ // -------------------------------------------------------------------------
6494
+ // Phase 3: Validation
6495
+ // -------------------------------------------------------------------------
6496
+ async validateSkill(content) {
6497
+ const prompt = loadBuilderPrompt("skill-validation.md", {
6498
+ skill_content: content
6499
+ });
6500
+ try {
6501
+ const response = await this.llmCall([
6502
+ { role: "system", content: prompt },
6503
+ { role: "user", content: "Validate this SKILL.md." }
6504
+ ]);
6505
+ const jsonStr = extractJSON(response);
6506
+ return JSON.parse(jsonStr);
6507
+ } catch {
6508
+ return {
6509
+ scores: { structure: 3, actionability: 3, completeness: 3, verification: 3, conciseness: 3 },
6510
+ overall: 3,
6511
+ pass: true,
6512
+ fixes: []
6513
+ };
6514
+ }
6515
+ }
6516
+ // -------------------------------------------------------------------------
6517
+ // Phase 3b: Refinement (if validation fails)
6518
+ // -------------------------------------------------------------------------
6519
+ async refineSkill(content, fixes) {
6520
+ const fixList = fixes.map((f, i) => `${i + 1}. ${f}`).join("\n");
6521
+ const response = await this.llmCall([
6522
+ {
6523
+ role: "system",
6524
+ content: "You are a skill definition editor. Apply the requested fixes to the SKILL.md content. Output ONLY the corrected SKILL.md content (starting with --- frontmatter). Do not explain changes or add commentary."
6525
+ },
6526
+ {
6527
+ role: "user",
6528
+ content: `Apply these fixes to the SKILL.md:
6529
+
6530
+ ${fixList}
6531
+
6532
+ ---
6533
+
6534
+ Current SKILL.md:
6535
+
6536
+ ${content}`
6537
+ }
6538
+ ]);
6539
+ let refined = response.trim();
6540
+ if (refined.startsWith("```markdown"))
6541
+ refined = refined.slice("```markdown".length).trim();
6542
+ else if (refined.startsWith("```"))
6543
+ refined = refined.slice(3).trim();
6544
+ if (refined.endsWith("```"))
6545
+ refined = refined.slice(0, -3).trim();
6546
+ return refined.startsWith("---") ? refined : content;
6547
+ }
6548
+ };
6549
+ }
6550
+ });
6551
+
6285
6552
  // packages/execution/dist/tools/transcribe-tool.js
6286
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, readFileSync as readFileSync9, unlinkSync } from "node:fs";
6287
- import { join as join15, basename as basename4, extname as extname3, resolve as resolve13 } from "node:path";
6553
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readFileSync as readFileSync10, unlinkSync } from "node:fs";
6554
+ import { join as join16, basename as basename4, extname as extname3, resolve as resolve13 } from "node:path";
6288
6555
  import { homedir as homedir6 } from "node:os";
6289
6556
  import { execSync as execSync10, spawn as spawn4 } from "node:child_process";
6290
6557
  function isTranscribable(path) {
@@ -6301,25 +6568,25 @@ async function loadTranscribeCli() {
6301
6568
  timeout: 5e3,
6302
6569
  stdio: ["pipe", "pipe", "pipe"]
6303
6570
  }).trim();
6304
- const tcPath = join15(globalRoot, "transcribe-cli");
6305
- if (existsSync12(join15(tcPath, "dist", "index.js"))) {
6571
+ const tcPath = join16(globalRoot, "transcribe-cli");
6572
+ if (existsSync13(join16(tcPath, "dist", "index.js"))) {
6306
6573
  const { createRequire: createRequire4 } = await import("node:module");
6307
6574
  const req = createRequire4(import.meta.url);
6308
- _tcModule = req(join15(tcPath, "dist", "index.js"));
6575
+ _tcModule = req(join16(tcPath, "dist", "index.js"));
6309
6576
  return _tcModule;
6310
6577
  }
6311
6578
  } catch {
6312
6579
  }
6313
- const nvmBase = join15(homedir6(), ".nvm", "versions", "node");
6314
- if (existsSync12(nvmBase)) {
6580
+ const nvmBase = join16(homedir6(), ".nvm", "versions", "node");
6581
+ if (existsSync13(nvmBase)) {
6315
6582
  try {
6316
6583
  const { readdirSync: readdirSync15 } = await import("node:fs");
6317
6584
  for (const ver of readdirSync15(nvmBase)) {
6318
- const tcPath = join15(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
6319
- if (existsSync12(join15(tcPath, "dist", "index.js"))) {
6585
+ const tcPath = join16(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
6586
+ if (existsSync13(join16(tcPath, "dist", "index.js"))) {
6320
6587
  const { createRequire: createRequire4 } = await import("node:module");
6321
6588
  const req = createRequire4(import.meta.url);
6322
- _tcModule = req(join15(tcPath, "dist", "index.js"));
6589
+ _tcModule = req(join16(tcPath, "dist", "index.js"));
6323
6590
  return _tcModule;
6324
6591
  }
6325
6592
  }
@@ -6391,7 +6658,7 @@ var init_transcribe_tool = __esm({
6391
6658
  const filePath = resolve13(this.workingDir, String(args["path"] ?? ""));
6392
6659
  const model = String(args["model"] ?? "base");
6393
6660
  const diarize = Boolean(args["diarize"] ?? false);
6394
- if (!existsSync12(filePath)) {
6661
+ if (!existsSync13(filePath)) {
6395
6662
  return {
6396
6663
  success: false,
6397
6664
  output: "",
@@ -6418,10 +6685,10 @@ var init_transcribe_tool = __esm({
6418
6685
  diarize,
6419
6686
  wordTimestamps: false
6420
6687
  });
6421
- const transcriptDir = join15(this.workingDir, ".oa", "transcripts");
6422
- mkdirSync4(transcriptDir, { recursive: true });
6423
- const outFile = join15(transcriptDir, `${basename4(filePath)}.txt`);
6424
- writeFileSync4(outFile, result.text, "utf-8");
6688
+ const transcriptDir = join16(this.workingDir, ".oa", "transcripts");
6689
+ mkdirSync5(transcriptDir, { recursive: true });
6690
+ const outFile = join16(transcriptDir, `${basename4(filePath)}.txt`);
6691
+ writeFileSync5(outFile, result.text, "utf-8");
6425
6692
  const lines = [
6426
6693
  `Transcription of: ${basename4(filePath)}`,
6427
6694
  `Model: ${model} | Language: ${result.language} | Duration: ${result.duration ? `${result.duration.toFixed(1)}s` : "unknown"}`,
@@ -6518,14 +6785,14 @@ var init_transcribe_tool = __esm({
6518
6785
  durationMs: performance.now() - start
6519
6786
  };
6520
6787
  }
6521
- const tmpDir = join15(this.workingDir, ".oa", "tmp");
6522
- mkdirSync4(tmpDir, { recursive: true });
6788
+ const tmpDir = join16(this.workingDir, ".oa", "tmp");
6789
+ mkdirSync5(tmpDir, { recursive: true });
6523
6790
  const urlPath = new URL(url).pathname;
6524
6791
  let ext = extname3(urlPath).toLowerCase();
6525
6792
  if (!ext || !AUDIO_EXTS.has(ext) && !VIDEO_EXTS.has(ext)) {
6526
6793
  ext = ".mp3";
6527
6794
  }
6528
- const tmpFile = join15(tmpDir, `download-${Date.now()}${ext}`);
6795
+ const tmpFile = join16(tmpDir, `download-${Date.now()}${ext}`);
6529
6796
  try {
6530
6797
  try {
6531
6798
  execSync10(`curl -sL -o "${tmpFile}" "${url}"`, {
@@ -6538,7 +6805,7 @@ var init_transcribe_tool = __esm({
6538
6805
  stdio: ["pipe", "pipe", "pipe"]
6539
6806
  });
6540
6807
  }
6541
- if (!existsSync12(tmpFile)) {
6808
+ if (!existsSync13(tmpFile)) {
6542
6809
  return {
6543
6810
  success: false,
6544
6811
  output: "",
@@ -6578,7 +6845,7 @@ ${result.output}`,
6578
6845
 
6579
6846
  // packages/execution/dist/tools/structured-file.js
6580
6847
  import { writeFile as writeFile6, mkdir as mkdir3 } from "node:fs/promises";
6581
- import { resolve as resolve14, dirname as dirname4, extname as extname4 } from "node:path";
6848
+ import { resolve as resolve14, dirname as dirname5, extname as extname4 } from "node:path";
6582
6849
  function jsonToCSV(data, separator = ",") {
6583
6850
  if (!Array.isArray(data) || data.length === 0)
6584
6851
  return "";
@@ -6693,7 +6960,7 @@ var init_structured_file = __esm({
6693
6960
  }
6694
6961
  try {
6695
6962
  const fullPath = resolve14(this.workingDir, filePath);
6696
- await mkdir3(dirname4(fullPath), { recursive: true });
6963
+ await mkdir3(dirname5(fullPath), { recursive: true });
6697
6964
  let content;
6698
6965
  let byteInfo = "";
6699
6966
  switch (format) {
@@ -6759,7 +7026,7 @@ var init_structured_file = __esm({
6759
7026
  // packages/execution/dist/tools/code-sandbox.js
6760
7027
  import { spawn as spawn5 } from "node:child_process";
6761
7028
  import { writeFile as writeFile7, mkdtemp, rm, readdir as readdir2, stat } from "node:fs/promises";
6762
- import { join as join16 } from "node:path";
7029
+ import { join as join17 } from "node:path";
6763
7030
  import { tmpdir as tmpdir2 } from "node:os";
6764
7031
  function runProcess(cmd, args, options) {
6765
7032
  return new Promise((resolve31) => {
@@ -6825,7 +7092,7 @@ async function listCreatedFiles(dir) {
6825
7092
  for (const entry of entries) {
6826
7093
  if (entry.startsWith("_sandbox_script"))
6827
7094
  continue;
6828
- const fullPath = join16(dir, entry);
7095
+ const fullPath = join17(dir, entry);
6829
7096
  const s = await stat(fullPath);
6830
7097
  if (s.isFile()) {
6831
7098
  files.push(entry);
@@ -6945,9 +7212,9 @@ ${result.filesCreated.join("\n")}`);
6945
7212
  // Subprocess mode — temp directory + separate process
6946
7213
  // -------------------------------------------------------------------------
6947
7214
  async #runSubprocess(code, langConfig, timeoutMs, stdin) {
6948
- const sandboxDir = await mkdtemp(join16(tmpdir2(), "oa-sandbox-"));
7215
+ const sandboxDir = await mkdtemp(join17(tmpdir2(), "oa-sandbox-"));
6949
7216
  try {
6950
- const scriptFile = join16(sandboxDir, `_sandbox_script${langConfig.ext}`);
7217
+ const scriptFile = join17(sandboxDir, `_sandbox_script${langConfig.ext}`);
6951
7218
  await writeFile7(scriptFile, code, "utf-8");
6952
7219
  const result = await runProcess(langConfig.cmd, langConfig.args(scriptFile), {
6953
7220
  cwd: sandboxDir,
@@ -6972,10 +7239,10 @@ ${result.filesCreated.join("\n")}`);
6972
7239
  bash: "bash:5"
6973
7240
  };
6974
7241
  const image = images[language] ?? "node:22-slim";
6975
- const sandboxDir = await mkdtemp(join16(tmpdir2(), "oa-docker-sandbox-"));
7242
+ const sandboxDir = await mkdtemp(join17(tmpdir2(), "oa-docker-sandbox-"));
6976
7243
  try {
6977
7244
  const scriptFile = `_sandbox_script${langConfig.ext}`;
6978
- await writeFile7(join16(sandboxDir, scriptFile), code, "utf-8");
7245
+ await writeFile7(join17(sandboxDir, scriptFile), code, "utf-8");
6979
7246
  const dockerArgs = [
6980
7247
  "run",
6981
7248
  "--rm",
@@ -7345,9 +7612,9 @@ ${parts.join("\n\n")}`,
7345
7612
  });
7346
7613
 
7347
7614
  // packages/execution/dist/tools/vision.js
7348
- import { readFileSync as readFileSync10, existsSync as existsSync13, statSync as statSync5 } from "node:fs";
7615
+ import { readFileSync as readFileSync11, existsSync as existsSync14, statSync as statSync5 } from "node:fs";
7349
7616
  import { execSync as execSync11, spawn as spawn6 } from "node:child_process";
7350
- import { resolve as resolve16, extname as extname6, basename as basename5, dirname as dirname5, join as join17 } from "node:path";
7617
+ import { resolve as resolve16, extname as extname6, basename as basename5, dirname as dirname6, join as join18 } from "node:path";
7351
7618
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7352
7619
  async function probeStation(endpoint) {
7353
7620
  try {
@@ -7362,24 +7629,24 @@ async function probeStation(endpoint) {
7362
7629
  }
7363
7630
  }
7364
7631
  function findStationBinary() {
7365
- const oaVenvPython = join17(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
7366
- if (existsSync13(oaVenvPython)) {
7632
+ const oaVenvPython = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
7633
+ if (existsSync14(oaVenvPython)) {
7367
7634
  try {
7368
7635
  execSync11(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
7369
7636
  return oaVenvPython;
7370
7637
  } catch {
7371
7638
  }
7372
7639
  }
7373
- const oaVenvBin = join17(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
7374
- if (existsSync13(oaVenvBin))
7640
+ const oaVenvBin = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
7641
+ if (existsSync14(oaVenvBin))
7375
7642
  return oaVenvBin;
7376
- const thisDir = dirname5(fileURLToPath2(import.meta.url));
7643
+ const thisDir = dirname6(fileURLToPath2(import.meta.url));
7377
7644
  const localVenvPaths = [
7378
7645
  resolve16(thisDir, "../../../../.moondream-venv/bin/python"),
7379
7646
  resolve16(thisDir, "../../../.moondream-venv/bin/python")
7380
7647
  ];
7381
7648
  for (const p of localVenvPaths) {
7382
- if (existsSync13(p)) {
7649
+ if (existsSync14(p)) {
7383
7650
  try {
7384
7651
  execSync11(`${JSON.stringify(p)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
7385
7652
  return p;
@@ -7399,9 +7666,9 @@ async function autoLaunchStation(port = 2020) {
7399
7666
  const pythonBin = findStationBinary();
7400
7667
  if (!pythonBin)
7401
7668
  return false;
7402
- const thisDir = dirname5(fileURLToPath2(import.meta.url));
7669
+ const thisDir = dirname6(fileURLToPath2(import.meta.url));
7403
7670
  const launcherScript = resolve16(thisDir, "../../scripts/start-moondream.py");
7404
- if (!existsSync13(launcherScript))
7671
+ if (!existsSync14(launcherScript))
7405
7672
  return false;
7406
7673
  return new Promise((resolvePromise) => {
7407
7674
  const child = spawn6(pythonBin, [launcherScript, "--port", String(port)], {
@@ -7476,7 +7743,7 @@ Details: ${err.message}` : "");
7476
7743
  }
7477
7744
  function loadImageBuffer(workingDir, rawPath) {
7478
7745
  const fullPath = resolve16(workingDir, rawPath);
7479
- if (!existsSync13(fullPath)) {
7746
+ if (!existsSync14(fullPath)) {
7480
7747
  throw new Error(`File not found: ${rawPath}`);
7481
7748
  }
7482
7749
  const stat5 = statSync5(fullPath);
@@ -7487,7 +7754,7 @@ function loadImageBuffer(workingDir, rawPath) {
7487
7754
  if (!IMAGE_EXTENSIONS2.has(ext)) {
7488
7755
  throw new Error(`Not a supported image format: ${ext}. Supported: ${[...IMAGE_EXTENSIONS2].join(", ")}`);
7489
7756
  }
7490
- return { buffer: readFileSync10(fullPath), fullPath };
7757
+ return { buffer: readFileSync11(fullPath), fullPath };
7491
7758
  }
7492
7759
  var moondreamClient, moondreamError, stationProcess, IMAGE_EXTENSIONS2, VisionTool;
7493
7760
  var init_vision = __esm({
@@ -7715,10 +7982,10 @@ ${response}`, durationMs: performance.now() - start };
7715
7982
  });
7716
7983
 
7717
7984
  // packages/execution/dist/tools/desktop-click.js
7718
- import { readFileSync as readFileSync11, existsSync as existsSync14 } from "node:fs";
7985
+ import { readFileSync as readFileSync12, existsSync as existsSync15 } from "node:fs";
7719
7986
  import { execSync as execSync12 } from "node:child_process";
7720
7987
  import { tmpdir as tmpdir3 } from "node:os";
7721
- import { join as join18, dirname as dirname6 } from "node:path";
7988
+ import { join as join19, dirname as dirname7 } from "node:path";
7722
7989
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7723
7990
  function hasCommand2(cmd) {
7724
7991
  try {
@@ -7780,7 +8047,7 @@ function captureScreenshot(outputPath) {
7780
8047
  } else {
7781
8048
  try {
7782
8049
  execSync12(`DISPLAY=:0 python3 -c "from PIL import ImageGrab; ImageGrab.grab().save(${JSON.stringify(outputPath)})"`, { stdio: "pipe", timeout: 1e4 });
7783
- if (existsSync14(outputPath))
8050
+ if (existsSync15(outputPath))
7784
8051
  return;
7785
8052
  } catch {
7786
8053
  }
@@ -7791,7 +8058,7 @@ function captureScreenshot(outputPath) {
7791
8058
  throw new Error("No screenshot tool found. Auto-install failed. Try manually: sudo apt install scrot");
7792
8059
  }
7793
8060
  execSync12(cmd, { stdio: "pipe", timeout: 1e4 });
7794
- if (!existsSync14(outputPath)) {
8061
+ if (!existsSync15(outputPath)) {
7795
8062
  throw new Error("Screenshot file was not created");
7796
8063
  }
7797
8064
  }
@@ -7842,7 +8109,7 @@ for i in range(${clicks}):
7842
8109
  } catch {
7843
8110
  }
7844
8111
  try {
7845
- const venvPy = join18(__dirname, "../../../../.moondream-venv/bin/python");
8112
+ const venvPy = join19(__dirname2, "../../../../.moondream-venv/bin/python");
7846
8113
  execSync12(`DISPLAY=:0 ${JSON.stringify(venvPy)} -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
7847
8114
  return;
7848
8115
  } catch {
@@ -7865,12 +8132,12 @@ for i in range(${clicks}):
7865
8132
  throw new Error(`Desktop click not supported on platform: ${plat}`);
7866
8133
  }
7867
8134
  }
7868
- var __dirname, DesktopClickTool, DesktopDescribeTool;
8135
+ var __dirname2, DesktopClickTool, DesktopDescribeTool;
7869
8136
  var init_desktop_click = __esm({
7870
8137
  "packages/execution/dist/tools/desktop-click.js"() {
7871
8138
  "use strict";
7872
8139
  init_system_deps();
7873
- __dirname = dirname6(fileURLToPath3(import.meta.url));
8140
+ __dirname2 = dirname7(fileURLToPath3(import.meta.url));
7874
8141
  DesktopClickTool = class {
7875
8142
  workingDir;
7876
8143
  name = "desktop_click";
@@ -7934,7 +8201,7 @@ var init_desktop_click = __esm({
7934
8201
  if (delayMs > 0) {
7935
8202
  await new Promise((r) => setTimeout(r, delayMs));
7936
8203
  }
7937
- const screenshotPath = join18(tmpdir3(), `oa-desktop-click-${Date.now()}.png`);
8204
+ const screenshotPath = join19(tmpdir3(), `oa-desktop-click-${Date.now()}.png`);
7938
8205
  captureScreenshot(screenshotPath);
7939
8206
  const dims = getImageDimensions2(screenshotPath);
7940
8207
  if (!dims) {
@@ -7959,7 +8226,7 @@ var init_desktop_click = __esm({
7959
8226
  } else {
7960
8227
  client = new vl({ endpoint: "http://localhost:2020/v1" });
7961
8228
  }
7962
- const imageBuffer = readFileSync11(screenshotPath);
8229
+ const imageBuffer = readFileSync12(screenshotPath);
7963
8230
  const pointResult = await client.point({ image: imageBuffer, object: target });
7964
8231
  points = pointResult.points ?? [];
7965
8232
  visionWorked = true;
@@ -7970,7 +8237,7 @@ var init_desktop_click = __esm({
7970
8237
  const ollamaHost = process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
7971
8238
  const envModel = process.env["OLLAMA_VISION_MODEL"];
7972
8239
  const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
7973
- const imageBase64 = readFileSync11(screenshotPath).toString("base64");
8240
+ const imageBase64 = readFileSync12(screenshotPath).toString("base64");
7974
8241
  const res = await fetch(`${ollamaHost}/api/generate`, {
7975
8242
  method: "POST",
7976
8243
  headers: { "Content-Type": "application/json" },
@@ -8109,10 +8376,10 @@ Screenshot: ${screenshotPath}`,
8109
8376
  if (delayMs > 0) {
8110
8377
  await new Promise((r) => setTimeout(r, delayMs));
8111
8378
  }
8112
- const screenshotPath = join18(tmpdir3(), `oa-desktop-describe-${Date.now()}.png`);
8379
+ const screenshotPath = join19(tmpdir3(), `oa-desktop-describe-${Date.now()}.png`);
8113
8380
  captureScreenshot(screenshotPath);
8114
8381
  const dims = getImageDimensions2(screenshotPath);
8115
- const imageBuffer = readFileSync11(screenshotPath);
8382
+ const imageBuffer = readFileSync12(screenshotPath);
8116
8383
  const parts = [];
8117
8384
  let visionWorked = false;
8118
8385
  try {
@@ -8224,7 +8491,7 @@ Screen: ${dims.width}x${dims.height}`);
8224
8491
  });
8225
8492
 
8226
8493
  // packages/execution/dist/tools/ocr-pdf.js
8227
- import { existsSync as existsSync15, statSync as statSync6 } from "node:fs";
8494
+ import { existsSync as existsSync16, statSync as statSync6 } from "node:fs";
8228
8495
  import { resolve as resolve17, basename as basename6 } from "node:path";
8229
8496
  import { execSync as execSync13 } from "node:child_process";
8230
8497
  var OcrPdfTool;
@@ -8276,7 +8543,7 @@ var init_ocr_pdf = __esm({
8276
8543
  return { success: false, output: "", error: "input path is required", durationMs: 0 };
8277
8544
  }
8278
8545
  const inputPath = resolve17(this.workingDir, rawInput);
8279
- if (!existsSync15(inputPath)) {
8546
+ if (!existsSync16(inputPath)) {
8280
8547
  return { success: false, output: "", error: `File not found: ${rawInput}`, durationMs: performance.now() - start };
8281
8548
  }
8282
8549
  const stat5 = statSync6(inputPath);
@@ -8347,8 +8614,8 @@ Language: ${language}
8347
8614
  });
8348
8615
 
8349
8616
  // packages/execution/dist/tools/pdf-to-text.js
8350
- import { existsSync as existsSync16, statSync as statSync7, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "node:fs";
8351
- import { resolve as resolve18, basename as basename7, join as join19 } from "node:path";
8617
+ import { existsSync as existsSync17, statSync as statSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync2 } from "node:fs";
8618
+ import { resolve as resolve18, basename as basename7, join as join20 } from "node:path";
8352
8619
  import { execSync as execSync14 } from "node:child_process";
8353
8620
  import { tmpdir as tmpdir4 } from "node:os";
8354
8621
  var PdfToTextTool;
@@ -8400,7 +8667,7 @@ var init_pdf_to_text = __esm({
8400
8667
  return { success: false, output: "", error: "path is required", durationMs: 0 };
8401
8668
  }
8402
8669
  const fullPath = resolve18(this.workingDir, rawPath);
8403
- if (!existsSync16(fullPath)) {
8670
+ if (!existsSync17(fullPath)) {
8404
8671
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
8405
8672
  }
8406
8673
  const fileStat = statSync7(fullPath);
@@ -8502,7 +8769,7 @@ ${text}`,
8502
8769
  if (!ocrCheck.available || !tesCheck.available || !gsCheck.available) {
8503
8770
  return null;
8504
8771
  }
8505
- const tmpPdf = join19(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
8772
+ const tmpPdf = join20(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
8506
8773
  try {
8507
8774
  const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
8508
8775
  execSync14(ocrCmd, { stdio: "pipe", timeout: 6e5 });
@@ -8532,27 +8799,27 @@ ${text}`,
8532
8799
  });
8533
8800
 
8534
8801
  // packages/execution/dist/tools/ocr-image-advanced.js
8535
- import { existsSync as existsSync17, statSync as statSync8 } from "node:fs";
8536
- import { resolve as resolve19, basename as basename8, dirname as dirname7, join as join20 } from "node:path";
8802
+ import { existsSync as existsSync18, statSync as statSync8 } from "node:fs";
8803
+ import { resolve as resolve19, basename as basename8, dirname as dirname8, join as join21 } from "node:path";
8537
8804
  import { execSync as execSync15 } from "node:child_process";
8538
8805
  import { fileURLToPath as fileURLToPath4 } from "node:url";
8539
8806
  import { homedir as homedir7, tmpdir as tmpdir5 } from "node:os";
8540
8807
  function findOcrScript() {
8541
- const thisDir = dirname7(fileURLToPath4(import.meta.url));
8808
+ const thisDir = dirname8(fileURLToPath4(import.meta.url));
8542
8809
  const devPath3 = resolve19(thisDir, "../../scripts/ocr-advanced.py");
8543
- if (existsSync17(devPath3))
8810
+ if (existsSync18(devPath3))
8544
8811
  return devPath3;
8545
8812
  const bundledPath = resolve19(thisDir, "../scripts/ocr-advanced.py");
8546
- if (existsSync17(bundledPath))
8813
+ if (existsSync18(bundledPath))
8547
8814
  return bundledPath;
8548
8815
  const sameDirPath = resolve19(thisDir, "ocr-advanced.py");
8549
- if (existsSync17(sameDirPath))
8816
+ if (existsSync18(sameDirPath))
8550
8817
  return sameDirPath;
8551
8818
  return null;
8552
8819
  }
8553
8820
  function findPython() {
8554
- const venvPython = join20(homedir7(), ".open-agents", "venv", "bin", "python");
8555
- if (existsSync17(venvPython)) {
8821
+ const venvPython = join21(homedir7(), ".open-agents", "venv", "bin", "python");
8822
+ if (existsSync18(venvPython)) {
8556
8823
  try {
8557
8824
  execSync15(`${JSON.stringify(venvPython)} -c "import cv2, pytesseract, numpy, PIL"`, {
8558
8825
  stdio: "pipe",
@@ -8636,7 +8903,7 @@ var init_ocr_image_advanced = __esm({
8636
8903
  return { success: false, output: "", error: "image path is required", durationMs: 0 };
8637
8904
  }
8638
8905
  const fullPath = resolve19(this.workingDir, rawPath);
8639
- if (!existsSync17(fullPath)) {
8906
+ if (!existsSync18(fullPath)) {
8640
8907
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
8641
8908
  }
8642
8909
  if (!batch) {
@@ -8697,7 +8964,7 @@ var init_ocr_image_advanced = __esm({
8697
8964
  cmdParts.push("--output-dir", JSON.stringify(resolve19(this.workingDir, outputDir)));
8698
8965
  let debugDir;
8699
8966
  if (debug) {
8700
- debugDir = join20(tmpdir5(), `oa-ocr-debug-${Date.now()}`);
8967
+ debugDir = join21(tmpdir5(), `oa-ocr-debug-${Date.now()}`);
8701
8968
  cmdParts.push("--debug-dir", debugDir);
8702
8969
  }
8703
8970
  try {
@@ -8796,7 +9063,7 @@ var init_ocr_image_advanced = __esm({
8796
9063
  if (region) {
8797
9064
  try {
8798
9065
  const [x, y, w, h] = region.split(",").map(Number);
8799
- const croppedPath = join20(tmpdir5(), `oa-ocr-crop-${Date.now()}.png`);
9066
+ const croppedPath = join21(tmpdir5(), `oa-ocr-crop-${Date.now()}.png`);
8800
9067
  execSync15(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
8801
9068
  inputPath = croppedPath;
8802
9069
  } catch {
@@ -8836,8 +9103,8 @@ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-
8836
9103
 
8837
9104
  // packages/execution/dist/tools/browser-action.js
8838
9105
  import { execSync as execSync16, spawn as spawn7 } from "node:child_process";
8839
- import { existsSync as existsSync18, readFileSync as readFileSync13 } from "node:fs";
8840
- import { join as join21, dirname as dirname8 } from "node:path";
9106
+ import { existsSync as existsSync19, readFileSync as readFileSync14 } from "node:fs";
9107
+ import { join as join22, dirname as dirname9 } from "node:path";
8841
9108
  import { fileURLToPath as fileURLToPath5 } from "node:url";
8842
9109
  async function probeService() {
8843
9110
  try {
@@ -8867,7 +9134,7 @@ async function launchService() {
8867
9134
  const python = findPython2();
8868
9135
  if (!python)
8869
9136
  return "Python 3 not found. Install Python 3.9+ to use browser automation.";
8870
- if (!existsSync18(SCRAPE_SCRIPT)) {
9137
+ if (!existsSync19(SCRAPE_SCRIPT)) {
8871
9138
  return `Scrape service script not found at ${SCRAPE_SCRIPT}`;
8872
9139
  }
8873
9140
  serviceProcess = spawn7(python, [SCRAPE_SCRIPT], {
@@ -8924,12 +9191,12 @@ async function apiCall(endpoint, method = "POST", body) {
8924
9191
  const res = await fetch(url, options);
8925
9192
  return await res.json();
8926
9193
  }
8927
- var __dirname2, SCRAPE_SCRIPT, DEFAULT_PORT, BASE_URL, serviceProcess, activeSessionId, BrowserActionTool;
9194
+ var __dirname3, SCRAPE_SCRIPT, DEFAULT_PORT, BASE_URL, serviceProcess, activeSessionId, BrowserActionTool;
8928
9195
  var init_browser_action = __esm({
8929
9196
  "packages/execution/dist/tools/browser-action.js"() {
8930
9197
  "use strict";
8931
- __dirname2 = dirname8(fileURLToPath5(import.meta.url));
8932
- SCRAPE_SCRIPT = join21(__dirname2, "..", "..", "scripts", "web_scrape.py");
9198
+ __dirname3 = dirname9(fileURLToPath5(import.meta.url));
9199
+ SCRAPE_SCRIPT = join22(__dirname3, "..", "..", "scripts", "web_scrape.py");
8933
9200
  DEFAULT_PORT = 8130;
8934
9201
  BASE_URL = `http://localhost:${DEFAULT_PORT}`;
8935
9202
  serviceProcess = null;
@@ -9089,19 +9356,19 @@ var init_browser_action = __esm({
9089
9356
 
9090
9357
  // packages/execution/dist/tools/autoresearch.js
9091
9358
  import { execSync as execSync17, spawn as spawn8 } from "node:child_process";
9092
- import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, appendFileSync, copyFileSync } from "node:fs";
9093
- import { join as join22, resolve as resolve20, dirname as dirname9 } from "node:path";
9359
+ import { existsSync as existsSync20, readFileSync as readFileSync15, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, appendFileSync, copyFileSync } from "node:fs";
9360
+ import { join as join23, resolve as resolve20, dirname as dirname10 } from "node:path";
9094
9361
  import { fileURLToPath as fileURLToPath6 } from "node:url";
9095
9362
  function findAutoresearchScript(scriptName) {
9096
- const thisDir = dirname9(fileURLToPath6(import.meta.url));
9363
+ const thisDir = dirname10(fileURLToPath6(import.meta.url));
9097
9364
  const devPath3 = resolve20(thisDir, "../../scripts", scriptName);
9098
- if (existsSync19(devPath3))
9365
+ if (existsSync20(devPath3))
9099
9366
  return devPath3;
9100
9367
  const bundledPath = resolve20(thisDir, "../scripts", scriptName);
9101
- if (existsSync19(bundledPath))
9368
+ if (existsSync20(bundledPath))
9102
9369
  return bundledPath;
9103
9370
  const sameDirPath = resolve20(thisDir, scriptName);
9104
- if (existsSync19(sameDirPath))
9371
+ if (existsSync20(sameDirPath))
9105
9372
  return sameDirPath;
9106
9373
  return null;
9107
9374
  }
@@ -9192,7 +9459,7 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
9192
9459
  async execute(args) {
9193
9460
  const start = Date.now();
9194
9461
  const action = String(args["action"] ?? "status");
9195
- const workspacePath = String(args["workspace"] ?? join22(this.repoRoot, ".oa", "autoresearch"));
9462
+ const workspacePath = String(args["workspace"] ?? join23(this.repoRoot, ".oa", "autoresearch"));
9196
9463
  try {
9197
9464
  switch (action) {
9198
9465
  case "setup":
@@ -9229,17 +9496,17 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
9229
9496
  } catch {
9230
9497
  output.push("GPU: detection failed (nvidia-smi not available)");
9231
9498
  }
9232
- mkdirSync5(workspace, { recursive: true });
9499
+ mkdirSync6(workspace, { recursive: true });
9233
9500
  const prepareScript = findAutoresearchScript("autoresearch-prepare.py");
9234
9501
  const trainScript = findAutoresearchScript("autoresearch-train.py");
9235
9502
  if (prepareScript) {
9236
- copyFileSync(prepareScript, join22(workspace, "prepare.py"));
9503
+ copyFileSync(prepareScript, join23(workspace, "prepare.py"));
9237
9504
  output.push("Copied prepare.py template");
9238
9505
  } else {
9239
9506
  return { success: false, output: output.join("\n"), error: "autoresearch-prepare.py template not found in distribution", durationMs: Date.now() - start };
9240
9507
  }
9241
9508
  if (trainScript) {
9242
- copyFileSync(trainScript, join22(workspace, "train.py"));
9509
+ copyFileSync(trainScript, join23(workspace, "train.py"));
9243
9510
  output.push("Copied train.py template");
9244
9511
  } else {
9245
9512
  return { success: false, output: output.join("\n"), error: "autoresearch-train.py template not found in distribution", durationMs: Date.now() - start };
@@ -9271,7 +9538,7 @@ name = "pytorch-cu128"
9271
9538
  url = "https://download.pytorch.org/whl/cu128"
9272
9539
  explicit = true
9273
9540
  `;
9274
- writeFileSync5(join22(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
9541
+ writeFileSync6(join23(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
9275
9542
  output.push("Created pyproject.toml");
9276
9543
  try {
9277
9544
  execSync17("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
@@ -9313,9 +9580,9 @@ explicit = true
9313
9580
  const e = err;
9314
9581
  output.push(`Data prep warning: ${(e.stderr ?? e.stdout ?? "failed").slice(0, 500)}`);
9315
9582
  }
9316
- const tsvPath = join22(workspace, "results.tsv");
9317
- if (!existsSync19(tsvPath)) {
9318
- writeFileSync5(tsvPath, "commit val_bpb memory_gb status description\n", "utf-8");
9583
+ const tsvPath = join23(workspace, "results.tsv");
9584
+ if (!existsSync20(tsvPath)) {
9585
+ writeFileSync6(tsvPath, "commit val_bpb memory_gb status description\n", "utf-8");
9319
9586
  output.push("Created results.tsv");
9320
9587
  }
9321
9588
  return {
@@ -9335,10 +9602,10 @@ Next steps:
9335
9602
  }
9336
9603
  // ── Run experiment ─────────────────────────────────────────────────────
9337
9604
  async run(workspace, args, start) {
9338
- if (!existsSync19(join22(workspace, "train.py"))) {
9605
+ if (!existsSync20(join23(workspace, "train.py"))) {
9339
9606
  return { success: false, output: "", error: `No train.py found in ${workspace}. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9340
9607
  }
9341
- if (!existsSync19(join22(workspace, ".venv")) && existsSync19(join22(workspace, "pyproject.toml"))) {
9608
+ if (!existsSync20(join23(workspace, ".venv")) && existsSync20(join23(workspace, "pyproject.toml"))) {
9342
9609
  try {
9343
9610
  execSync17("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
9344
9611
  } catch {
@@ -9346,7 +9613,7 @@ Next steps:
9346
9613
  }
9347
9614
  const timeoutMin = Number(args["timeout_minutes"] ?? 10);
9348
9615
  const timeoutMs = timeoutMin * 60 * 1e3;
9349
- const logPath = join22(workspace, "run.log");
9616
+ const logPath = join23(workspace, "run.log");
9350
9617
  return new Promise((resolveResult) => {
9351
9618
  const proc = spawn8("uv", ["run", "train.py"], {
9352
9619
  cwd: workspace,
@@ -9377,7 +9644,7 @@ Next steps:
9377
9644
  clearTimeout(timer);
9378
9645
  const fullLog = stdout + "\n" + stderr;
9379
9646
  try {
9380
- writeFileSync5(logPath, fullLog, "utf-8");
9647
+ writeFileSync6(logPath, fullLog, "utf-8");
9381
9648
  } catch {
9382
9649
  }
9383
9650
  if (timedOut) {
@@ -9417,7 +9684,7 @@ ${fullLog.slice(-2e3)}`,
9417
9684
  return;
9418
9685
  }
9419
9686
  try {
9420
- writeFileSync5(join22(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
9687
+ writeFileSync6(join23(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
9421
9688
  } catch {
9422
9689
  }
9423
9690
  const memGB = (result.peak_vram_mb / 1024).toFixed(1);
@@ -9453,11 +9720,11 @@ ${fullLog.slice(-2e3)}`,
9453
9720
  }
9454
9721
  // ── Results ────────────────────────────────────────────────────────────
9455
9722
  getResults(workspace, start) {
9456
- const tsvPath = join22(workspace, "results.tsv");
9457
- if (!existsSync19(tsvPath)) {
9723
+ const tsvPath = join23(workspace, "results.tsv");
9724
+ if (!existsSync20(tsvPath)) {
9458
9725
  return { success: false, output: "", error: `No results.tsv found. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9459
9726
  }
9460
- const content = readFileSync14(tsvPath, "utf-8");
9727
+ const content = readFileSync15(tsvPath, "utf-8");
9461
9728
  const lines = content.trim().split("\n");
9462
9729
  if (lines.length <= 1) {
9463
9730
  return { success: true, output: 'No experiments recorded yet. Run autoresearch(action="run") to start.', durationMs: Date.now() - start };
@@ -9480,7 +9747,7 @@ ${fullLog.slice(-2e3)}`,
9480
9747
  // ── Status ─────────────────────────────────────────────────────────────
9481
9748
  getStatus(workspace, start) {
9482
9749
  const output = [];
9483
- if (!existsSync19(join22(workspace, "train.py"))) {
9750
+ if (!existsSync20(join23(workspace, "train.py"))) {
9484
9751
  return {
9485
9752
  success: true,
9486
9753
  output: `Autoresearch workspace not initialized at ${workspace}.
@@ -9503,33 +9770,33 @@ Run autoresearch(action="setup") to begin.`,
9503
9770
  } catch {
9504
9771
  output.push("GPU: not detected");
9505
9772
  }
9506
- const lastResultPath = join22(workspace, ".last-result.json");
9507
- if (existsSync19(lastResultPath)) {
9773
+ const lastResultPath = join23(workspace, ".last-result.json");
9774
+ if (existsSync20(lastResultPath)) {
9508
9775
  try {
9509
- const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9776
+ const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
9510
9777
  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`);
9511
9778
  } catch {
9512
9779
  }
9513
9780
  }
9514
- const tsvPath = join22(workspace, "results.tsv");
9515
- if (existsSync19(tsvPath)) {
9516
- const lines = readFileSync14(tsvPath, "utf-8").trim().split("\n");
9781
+ const tsvPath = join23(workspace, "results.tsv");
9782
+ if (existsSync20(tsvPath)) {
9783
+ const lines = readFileSync15(tsvPath, "utf-8").trim().split("\n");
9517
9784
  output.push(`Experiments recorded: ${lines.length - 1}`);
9518
9785
  }
9519
- const cacheDir = join22(process.env["HOME"] ?? "~", ".cache", "autoresearch");
9520
- output.push(`Data cache: ${existsSync19(cacheDir) ? "present" : "not found"} (${cacheDir})`);
9786
+ const cacheDir = join23(process.env["HOME"] ?? "~", ".cache", "autoresearch");
9787
+ output.push(`Data cache: ${existsSync20(cacheDir) ? "present" : "not found"} (${cacheDir})`);
9521
9788
  return { success: true, output: output.join("\n"), durationMs: Date.now() - start };
9522
9789
  }
9523
9790
  // ── Keep / Discard ─────────────────────────────────────────────────────
9524
9791
  keepExperiment(workspace, args, start) {
9525
9792
  const desc = String(args["description"] ?? "experiment");
9526
- const tsvPath = join22(workspace, "results.tsv");
9527
- const lastResultPath = join22(workspace, ".last-result.json");
9793
+ const tsvPath = join23(workspace, "results.tsv");
9794
+ const lastResultPath = join23(workspace, ".last-result.json");
9528
9795
  let valBpb = args["val_bpb"];
9529
9796
  let memGb = args["memory_gb"];
9530
- if ((valBpb === void 0 || memGb === void 0) && existsSync19(lastResultPath)) {
9797
+ if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
9531
9798
  try {
9532
- const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9799
+ const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
9533
9800
  if (valBpb === void 0)
9534
9801
  valBpb = last.val_bpb;
9535
9802
  if (memGb === void 0)
@@ -9562,13 +9829,13 @@ Branch advanced. Ready for next experiment.`,
9562
9829
  }
9563
9830
  discardExperiment(workspace, args, start) {
9564
9831
  const desc = String(args["description"] ?? "experiment");
9565
- const tsvPath = join22(workspace, "results.tsv");
9566
- const lastResultPath = join22(workspace, ".last-result.json");
9832
+ const tsvPath = join23(workspace, "results.tsv");
9833
+ const lastResultPath = join23(workspace, ".last-result.json");
9567
9834
  let valBpb = args["val_bpb"];
9568
9835
  let memGb = args["memory_gb"];
9569
- if ((valBpb === void 0 || memGb === void 0) && existsSync19(lastResultPath)) {
9836
+ if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
9570
9837
  try {
9571
- const last = JSON.parse(readFileSync14(lastResultPath, "utf-8"));
9838
+ const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
9572
9839
  if (valBpb === void 0)
9573
9840
  valBpb = last.val_bpb;
9574
9841
  if (memGb === void 0)
@@ -9610,7 +9877,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
9610
9877
  // packages/execution/dist/tools/scheduler.js
9611
9878
  import { execSync as execSync18, exec as execCb } from "node:child_process";
9612
9879
  import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir4 } from "node:fs/promises";
9613
- import { resolve as resolve21, join as join23 } from "node:path";
9880
+ import { resolve as resolve21, join as join24 } from "node:path";
9614
9881
  import { randomBytes as randomBytes2 } from "node:crypto";
9615
9882
  function isValidCron(expr) {
9616
9883
  const parts = expr.trim().split(/\s+/);
@@ -9694,7 +9961,7 @@ function installCronJob(task, workingDir) {
9694
9961
  const lines = getCurrentCrontab();
9695
9962
  const oaBin = findOaBinary();
9696
9963
  const logDir = resolve21(workingDir, ".oa", "scheduled", "logs");
9697
- const logFile = join23(logDir, `${task.id}.log`);
9964
+ const logFile = join24(logDir, `${task.id}.log`);
9698
9965
  const storeFile = resolve21(workingDir, ".oa", "scheduled", "tasks.json");
9699
9966
  const taskEscaped = task.task.replace(/'/g, "'\\''");
9700
9967
  const taskId = task.id;
@@ -9736,9 +10003,9 @@ async function loadStore(workingDir) {
9736
10003
  async function saveStore(workingDir, store) {
9737
10004
  const dir = resolve21(workingDir, ".oa", "scheduled");
9738
10005
  await mkdir4(dir, { recursive: true });
9739
- await mkdir4(join23(dir, "logs"), { recursive: true });
10006
+ await mkdir4(join24(dir, "logs"), { recursive: true });
9740
10007
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
9741
- await writeFile8(join23(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
10008
+ await writeFile8(join24(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
9742
10009
  }
9743
10010
  var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
9744
10011
  var init_scheduler = __esm({
@@ -9972,7 +10239,7 @@ ${truncated}`, durationMs: performance.now() - start };
9972
10239
 
9973
10240
  // packages/execution/dist/tools/reminder.js
9974
10241
  import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir5 } from "node:fs/promises";
9975
- import { resolve as resolve22, join as join24 } from "node:path";
10242
+ import { resolve as resolve22, join as join25 } from "node:path";
9976
10243
  import { randomBytes as randomBytes3 } from "node:crypto";
9977
10244
  function parseDueTime(due) {
9978
10245
  const lower = due.toLowerCase().trim();
@@ -10024,7 +10291,7 @@ function parseDueTime(due) {
10024
10291
  async function getStorePath(workingDir) {
10025
10292
  const dir = resolve22(workingDir, ".oa", "scheduled");
10026
10293
  await mkdir5(dir, { recursive: true });
10027
- return join24(dir, STORE_FILE);
10294
+ return join25(dir, STORE_FILE);
10028
10295
  }
10029
10296
  async function loadReminderStore(workingDir) {
10030
10297
  const storePath = await getStorePath(workingDir);
@@ -10285,7 +10552,7 @@ var init_reminder = __esm({
10285
10552
 
10286
10553
  // packages/execution/dist/tools/agenda.js
10287
10554
  import { readFile as readFile11, writeFile as writeFile10, mkdir as mkdir6 } from "node:fs/promises";
10288
- import { resolve as resolve23, join as join25 } from "node:path";
10555
+ import { resolve as resolve23, join as join26 } from "node:path";
10289
10556
  import { randomBytes as randomBytes4 } from "node:crypto";
10290
10557
  async function loadAttentionStore(workingDir) {
10291
10558
  const storePath = resolve23(workingDir, ".oa", "scheduled", "attention.json");
@@ -10300,7 +10567,7 @@ async function saveAttentionStore(workingDir, store) {
10300
10567
  const dir = resolve23(workingDir, ".oa", "scheduled");
10301
10568
  await mkdir6(dir, { recursive: true });
10302
10569
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
10303
- await writeFile10(join25(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
10570
+ await writeFile10(join26(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
10304
10571
  }
10305
10572
  async function getActiveAttentionItems(workingDir) {
10306
10573
  const store = await loadAttentionStore(workingDir);
@@ -10609,8 +10876,8 @@ ${sections.join("\n")}`,
10609
10876
 
10610
10877
  // packages/execution/dist/tools/opencode.js
10611
10878
  import { execSync as execSync19, spawn as spawn9 } from "node:child_process";
10612
- import { existsSync as existsSync20 } from "node:fs";
10613
- import { join as join26, resolve as resolve24 } from "node:path";
10879
+ import { existsSync as existsSync21 } from "node:fs";
10880
+ import { join as join27, resolve as resolve24 } from "node:path";
10614
10881
  function findOpencode() {
10615
10882
  for (const cmd of ["opencode"]) {
10616
10883
  try {
@@ -10622,12 +10889,12 @@ function findOpencode() {
10622
10889
  }
10623
10890
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
10624
10891
  const candidates = [
10625
- join26(homeDir, ".opencode", "bin", "opencode"),
10626
- join26(homeDir, "bin", "opencode"),
10892
+ join27(homeDir, ".opencode", "bin", "opencode"),
10893
+ join27(homeDir, "bin", "opencode"),
10627
10894
  "/usr/local/bin/opencode"
10628
10895
  ];
10629
10896
  for (const p of candidates) {
10630
- if (existsSync20(p))
10897
+ if (existsSync21(p))
10631
10898
  return p;
10632
10899
  }
10633
10900
  return null;
@@ -10883,8 +11150,8 @@ var init_opencode = __esm({
10883
11150
 
10884
11151
  // packages/execution/dist/tools/factory.js
10885
11152
  import { execSync as execSync20, spawn as spawn10 } from "node:child_process";
10886
- import { existsSync as existsSync21 } from "node:fs";
10887
- import { join as join27 } from "node:path";
11153
+ import { existsSync as existsSync22 } from "node:fs";
11154
+ import { join as join28 } from "node:path";
10888
11155
  function findDroid() {
10889
11156
  for (const cmd of ["droid"]) {
10890
11157
  try {
@@ -10896,12 +11163,12 @@ function findDroid() {
10896
11163
  }
10897
11164
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
10898
11165
  const candidates = [
10899
- join27(homeDir, ".factory", "bin", "droid"),
10900
- join27(homeDir, "bin", "droid"),
11166
+ join28(homeDir, ".factory", "bin", "droid"),
11167
+ join28(homeDir, "bin", "droid"),
10901
11168
  "/usr/local/bin/droid"
10902
11169
  ];
10903
11170
  for (const p of candidates) {
10904
- if (existsSync21(p))
11171
+ if (existsSync22(p))
10905
11172
  return p;
10906
11173
  }
10907
11174
  return null;
@@ -11193,7 +11460,7 @@ var init_factory = __esm({
11193
11460
  // packages/execution/dist/tools/cron-agent.js
11194
11461
  import { execSync as execSync21 } from "node:child_process";
11195
11462
  import { readFile as readFile12, writeFile as writeFile11, mkdir as mkdir7 } from "node:fs/promises";
11196
- import { resolve as resolve25, join as join28 } from "node:path";
11463
+ import { resolve as resolve25, join as join29 } from "node:path";
11197
11464
  import { randomBytes as randomBytes5 } from "node:crypto";
11198
11465
  function isValidCron2(expr) {
11199
11466
  const parts = expr.trim().split(/\s+/);
@@ -11279,7 +11546,7 @@ function installCronAgentJob(job, workingDir) {
11279
11546
  const lines = getCurrentCrontab2();
11280
11547
  const oaBin = findOaBinary2();
11281
11548
  const logDir = resolve25(workingDir, ".oa", "cron-agents", "logs");
11282
- const logFile = join28(logDir, `${job.id}.log`);
11549
+ const logFile = join29(logDir, `${job.id}.log`);
11283
11550
  const storeFile = resolve25(workingDir, ".oa", "cron-agents", "store.json");
11284
11551
  const taskEscaped = job.task.replace(/'/g, "'\\''");
11285
11552
  const jobId = job.id;
@@ -11318,9 +11585,9 @@ async function loadStore2(workingDir) {
11318
11585
  async function saveStore2(workingDir, store) {
11319
11586
  const dir = resolve25(workingDir, ".oa", "cron-agents");
11320
11587
  await mkdir7(dir, { recursive: true });
11321
- await mkdir7(join28(dir, "logs"), { recursive: true });
11588
+ await mkdir7(join29(dir, "logs"), { recursive: true });
11322
11589
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
11323
- await writeFile11(join28(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
11590
+ await writeFile11(join29(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
11324
11591
  }
11325
11592
  var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
11326
11593
  var init_cron_agent = __esm({
@@ -11657,8 +11924,8 @@ ${truncated}`, durationMs: performance.now() - start };
11657
11924
 
11658
11925
  // packages/execution/dist/tools/nexus.js
11659
11926
  import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3, open as fsOpen } from "node:fs/promises";
11660
- import { existsSync as existsSync22, readFileSync as readFileSync15 } from "node:fs";
11661
- import { resolve as resolve26, join as join29 } from "node:path";
11927
+ import { existsSync as existsSync23, readFileSync as readFileSync16 } from "node:fs";
11928
+ import { resolve as resolve26, join as join30 } from "node:path";
11662
11929
  import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
11663
11930
  import { execSync as execSync22, spawn as spawn11 } from "node:child_process";
11664
11931
  import { hostname, userInfo } from "node:os";
@@ -12694,7 +12961,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12694
12961
  this.nexusDir = resolve26(repoRoot, ".oa", "nexus");
12695
12962
  }
12696
12963
  async ensureDir() {
12697
- if (!existsSync22(this.nexusDir)) {
12964
+ if (!existsSync23(this.nexusDir)) {
12698
12965
  await mkdir8(this.nexusDir, { recursive: true });
12699
12966
  }
12700
12967
  }
@@ -12809,11 +13076,11 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12809
13076
  // Daemon management
12810
13077
  // =========================================================================
12811
13078
  getDaemonPid() {
12812
- const pidFile = join29(this.nexusDir, "daemon.pid");
12813
- if (!existsSync22(pidFile))
13079
+ const pidFile = join30(this.nexusDir, "daemon.pid");
13080
+ if (!existsSync23(pidFile))
12814
13081
  return null;
12815
13082
  try {
12816
- const pid = parseInt(readFileSync15(pidFile, "utf8").trim(), 10);
13083
+ const pid = parseInt(readFileSync16(pidFile, "utf8").trim(), 10);
12817
13084
  process.kill(pid, 0);
12818
13085
  return pid;
12819
13086
  } catch {
@@ -12825,16 +13092,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12825
13092
  if (!pid)
12826
13093
  throw new Error("Nexus daemon not running. Use action 'connect' first.");
12827
13094
  const cmdId = randomBytes6(8).toString("hex");
12828
- const cmdFile = join29(this.nexusDir, "cmd.json");
12829
- const respFile = join29(this.nexusDir, "resp.json");
12830
- if (existsSync22(respFile))
13095
+ const cmdFile = join30(this.nexusDir, "cmd.json");
13096
+ const respFile = join30(this.nexusDir, "resp.json");
13097
+ if (existsSync23(respFile))
12831
13098
  await unlink(respFile).catch(() => {
12832
13099
  });
12833
13100
  await writeFile12(cmdFile, JSON.stringify({ id: cmdId, action, args }, null, 2));
12834
13101
  const polls = Math.ceil(timeoutMs / 500);
12835
13102
  for (let i = 0; i < polls; i++) {
12836
13103
  await new Promise((r) => setTimeout(r, 500));
12837
- if (!existsSync22(respFile))
13104
+ if (!existsSync23(respFile))
12838
13105
  continue;
12839
13106
  try {
12840
13107
  const resp = JSON.parse(await readFile13(respFile, "utf8"));
@@ -12861,8 +13128,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12861
13128
  await this.ensureDir();
12862
13129
  const existingPid = this.getDaemonPid();
12863
13130
  if (existingPid) {
12864
- const statusFile2 = join29(this.nexusDir, "status.json");
12865
- if (existsSync22(statusFile2)) {
13131
+ const statusFile2 = join30(this.nexusDir, "status.json");
13132
+ if (existsSync23(statusFile2)) {
12866
13133
  try {
12867
13134
  const status = JSON.parse(await readFile13(statusFile2, "utf8"));
12868
13135
  if (status.connected && status.peerId) {
@@ -12878,8 +13145,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12878
13145
  await new Promise((r) => setTimeout(r, 500));
12879
13146
  }
12880
13147
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
12881
- const p = join29(this.nexusDir, f);
12882
- if (existsSync22(p))
13148
+ const p = join30(this.nexusDir, f);
13149
+ if (existsSync23(p))
12883
13150
  await unlink(p).catch(() => {
12884
13151
  });
12885
13152
  }
@@ -12887,21 +13154,21 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12887
13154
  let nexusResolved = false;
12888
13155
  let installedVersion = "";
12889
13156
  try {
12890
- const nexusPkg = join29(nodeModulesDir, "open-agents-nexus", "package.json");
12891
- if (existsSync22(nexusPkg)) {
13157
+ const nexusPkg = join30(nodeModulesDir, "open-agents-nexus", "package.json");
13158
+ if (existsSync23(nexusPkg)) {
12892
13159
  nexusResolved = true;
12893
13160
  try {
12894
- const pkg = JSON.parse(readFileSync15(nexusPkg, "utf8"));
13161
+ const pkg = JSON.parse(readFileSync16(nexusPkg, "utf8"));
12895
13162
  installedVersion = pkg.version || "";
12896
13163
  } catch {
12897
13164
  }
12898
13165
  } else {
12899
13166
  const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
12900
- const globalPkg = join29(globalDir, "open-agents-nexus", "package.json");
12901
- if (existsSync22(globalPkg)) {
13167
+ const globalPkg = join30(globalDir, "open-agents-nexus", "package.json");
13168
+ if (existsSync23(globalPkg)) {
12902
13169
  nexusResolved = true;
12903
13170
  try {
12904
- const pkg = JSON.parse(readFileSync15(globalPkg, "utf8"));
13171
+ const pkg = JSON.parse(readFileSync16(globalPkg, "utf8"));
12905
13172
  installedVersion = pkg.version || "";
12906
13173
  } catch {
12907
13174
  }
@@ -12944,7 +13211,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12944
13211
  }
12945
13212
  }
12946
13213
  }
12947
- const daemonPath = join29(this.nexusDir, "nexus-daemon.mjs");
13214
+ const daemonPath = join30(this.nexusDir, "nexus-daemon.mjs");
12948
13215
  await writeFile12(daemonPath, DAEMON_SCRIPT);
12949
13216
  const agentName = args.agent_name || "open-agents-node";
12950
13217
  const agentType = args.agent_type || "general";
@@ -12969,10 +13236,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12969
13236
  child.stderr?.on("data", (d) => {
12970
13237
  earlyError += d.toString();
12971
13238
  });
12972
- const statusFile = join29(this.nexusDir, "status.json");
13239
+ const statusFile = join30(this.nexusDir, "status.json");
12973
13240
  for (let i = 0; i < 40; i++) {
12974
13241
  await new Promise((r) => setTimeout(r, 500));
12975
- if (existsSync22(statusFile)) {
13242
+ if (existsSync23(statusFile)) {
12976
13243
  try {
12977
13244
  const status = JSON.parse(await readFile13(statusFile, "utf8"));
12978
13245
  if (status.error) {
@@ -13013,8 +13280,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13013
13280
  } catch {
13014
13281
  }
13015
13282
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
13016
- const p = join29(this.nexusDir, f);
13017
- if (existsSync22(p))
13283
+ const p = join30(this.nexusDir, f);
13284
+ if (existsSync23(p))
13018
13285
  await unlink(p).catch(() => {
13019
13286
  });
13020
13287
  }
@@ -13024,8 +13291,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13024
13291
  const pid = this.getDaemonPid();
13025
13292
  if (!pid)
13026
13293
  return "Nexus daemon not running. Use action 'connect' to start.";
13027
- const statusFile = join29(this.nexusDir, "status.json");
13028
- if (!existsSync22(statusFile))
13294
+ const statusFile = join30(this.nexusDir, "status.json");
13295
+ if (!existsSync23(statusFile))
13029
13296
  return `Daemon running (pid: ${pid}) but no status yet.`;
13030
13297
  try {
13031
13298
  const status = JSON.parse(await readFile13(statusFile, "utf8"));
@@ -13039,8 +13306,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13039
13306
  ` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
13040
13307
  ` Blocked peers: ${(status.blockedPeers || []).length || 0}`
13041
13308
  ];
13042
- const walletPath = join29(this.nexusDir, "wallet.enc");
13043
- if (existsSync22(walletPath)) {
13309
+ const walletPath = join30(this.nexusDir, "wallet.enc");
13310
+ if (existsSync23(walletPath)) {
13044
13311
  try {
13045
13312
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
13046
13313
  lines.push(` Wallet: ${w.address}`);
@@ -13050,14 +13317,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13050
13317
  } else {
13051
13318
  lines.push(` Wallet: not configured`);
13052
13319
  }
13053
- const inboxDir = join29(this.nexusDir, "inbox");
13054
- if (existsSync22(inboxDir)) {
13320
+ const inboxDir = join30(this.nexusDir, "inbox");
13321
+ if (existsSync23(inboxDir)) {
13055
13322
  try {
13056
13323
  const roomDirs = await readdir3(inboxDir);
13057
13324
  let totalMsgs = 0;
13058
13325
  for (const rd of roomDirs) {
13059
13326
  try {
13060
- totalMsgs += (await readdir3(join29(inboxDir, rd))).length;
13327
+ totalMsgs += (await readdir3(join30(inboxDir, rd))).length;
13061
13328
  } catch {
13062
13329
  }
13063
13330
  }
@@ -13104,10 +13371,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13104
13371
  }
13105
13372
  async doReadMessages(args) {
13106
13373
  const roomId = args.room_id;
13107
- const inboxDir = join29(this.nexusDir, "inbox");
13374
+ const inboxDir = join30(this.nexusDir, "inbox");
13108
13375
  if (roomId) {
13109
- const roomInbox = join29(inboxDir, roomId);
13110
- if (!existsSync22(roomInbox))
13376
+ const roomInbox = join30(inboxDir, roomId);
13377
+ if (!existsSync23(roomInbox))
13111
13378
  return `No messages in room: ${roomId}`;
13112
13379
  const files = (await readdir3(roomInbox)).sort().slice(-20);
13113
13380
  if (files.length === 0)
@@ -13115,7 +13382,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13115
13382
  const messages = [`Messages in ${roomId} (last ${files.length}):`];
13116
13383
  for (const f of files) {
13117
13384
  try {
13118
- const msg = JSON.parse(await readFile13(join29(roomInbox, f), "utf8"));
13385
+ const msg = JSON.parse(await readFile13(join30(roomInbox, f), "utf8"));
13119
13386
  const sender = (msg.sender || "unknown").slice(0, 12);
13120
13387
  messages.push(` [${new Date(msg.timestamp).toLocaleTimeString()}] ${sender}...: ${msg.content}`);
13121
13388
  } catch {
@@ -13123,7 +13390,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13123
13390
  }
13124
13391
  return messages.join("\n");
13125
13392
  }
13126
- if (!existsSync22(inboxDir))
13393
+ if (!existsSync23(inboxDir))
13127
13394
  return "No messages received yet.";
13128
13395
  const roomDirs = await readdir3(inboxDir);
13129
13396
  if (roomDirs.length === 0)
@@ -13131,7 +13398,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13131
13398
  const lines = ["Inbox:"];
13132
13399
  for (const rd of roomDirs) {
13133
13400
  try {
13134
- const count = (await readdir3(join29(inboxDir, rd))).length;
13401
+ const count = (await readdir3(join30(inboxDir, rd))).length;
13135
13402
  lines.push(` ${rd}: ${count} message(s)`);
13136
13403
  } catch {
13137
13404
  }
@@ -13143,8 +13410,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13143
13410
  // ---------------------------------------------------------------------------
13144
13411
  async doWalletStatus() {
13145
13412
  await this.ensureDir();
13146
- const walletPath = join29(this.nexusDir, "wallet.enc");
13147
- if (!existsSync22(walletPath)) {
13413
+ const walletPath = join30(this.nexusDir, "wallet.enc");
13414
+ if (!existsSync23(walletPath)) {
13148
13415
  return "No wallet configured. Use wallet_create to set one up.";
13149
13416
  }
13150
13417
  try {
@@ -13182,8 +13449,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13182
13449
  }
13183
13450
  async doWalletCreate(args) {
13184
13451
  await this.ensureDir();
13185
- const walletPath = join29(this.nexusDir, "wallet.enc");
13186
- if (existsSync22(walletPath))
13452
+ const walletPath = join30(this.nexusDir, "wallet.enc");
13453
+ if (existsSync23(walletPath))
13187
13454
  return "Wallet already exists. Delete wallet.enc to create a new one.";
13188
13455
  const userAddress = args.wallet_address;
13189
13456
  if (userAddress) {
@@ -13228,7 +13495,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13228
13495
  const cipher = createCipheriv("aes-256-gcm", key, iv);
13229
13496
  let enc = cipher.update(privKeyHex, "utf8", "hex");
13230
13497
  enc += cipher.final("hex");
13231
- const x402KeyPath = join29(this.nexusDir, "x402-wallet.key");
13498
+ const x402KeyPath = join30(this.nexusDir, "x402-wallet.key");
13232
13499
  const x402Fh = await fsOpen(x402KeyPath, "w", 384);
13233
13500
  await x402Fh.writeFile("0x" + privKeyHex);
13234
13501
  await x402Fh.close();
@@ -13299,8 +13566,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13299
13566
  // ---------------------------------------------------------------------------
13300
13567
  async doLedgerStatus() {
13301
13568
  await this.ensureDir();
13302
- const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13303
- if (!existsSync22(ledgerPath)) {
13569
+ const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
13570
+ if (!existsSync23(ledgerPath)) {
13304
13571
  return "No ledger entries. Earnings and spending will be tracked here after x402 transactions.";
13305
13572
  }
13306
13573
  try {
@@ -13341,8 +13608,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13341
13608
  }
13342
13609
  }
13343
13610
  async getLedgerSummary() {
13344
- const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13345
- if (!existsSync22(ledgerPath))
13611
+ const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
13612
+ if (!existsSync23(ledgerPath))
13346
13613
  return null;
13347
13614
  try {
13348
13615
  const raw = await readFile13(ledgerPath, "utf8");
@@ -13366,16 +13633,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13366
13633
  }
13367
13634
  async appendLedger(entry) {
13368
13635
  await this.ensureDir();
13369
- const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13636
+ const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
13370
13637
  const line = JSON.stringify(entry) + "\n";
13371
- await writeFile12(ledgerPath, existsSync22(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
13638
+ await writeFile12(ledgerPath, existsSync23(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
13372
13639
  }
13373
13640
  // ---------------------------------------------------------------------------
13374
13641
  // Step 4: Budget Policy — Spending limits and auto-approve thresholds
13375
13642
  // ---------------------------------------------------------------------------
13376
13643
  async loadBudget() {
13377
- const budgetPath = join29(this.nexusDir, "budget.json");
13378
- if (!existsSync22(budgetPath))
13644
+ const budgetPath = join30(this.nexusDir, "budget.json");
13645
+ if (!existsSync23(budgetPath))
13379
13646
  return null;
13380
13647
  try {
13381
13648
  return JSON.parse(await readFile13(budgetPath, "utf8"));
@@ -13384,8 +13651,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13384
13651
  }
13385
13652
  }
13386
13653
  async ensureDefaultBudget() {
13387
- const budgetPath = join29(this.nexusDir, "budget.json");
13388
- if (existsSync22(budgetPath))
13654
+ const budgetPath = join30(this.nexusDir, "budget.json");
13655
+ if (existsSync23(budgetPath))
13389
13656
  return;
13390
13657
  const defaultBudget = {
13391
13658
  version: 1,
@@ -13454,13 +13721,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13454
13721
  if (changes.length === 0) {
13455
13722
  return "No budget parameters provided. Use daily_limit, per_invoke_max, or auto_approve_below.";
13456
13723
  }
13457
- const budgetPath = join29(this.nexusDir, "budget.json");
13724
+ const budgetPath = join30(this.nexusDir, "budget.json");
13458
13725
  await writeFile12(budgetPath, JSON.stringify(budget, null, 2));
13459
13726
  return `Budget updated: ${changes.join(", ")}`;
13460
13727
  }
13461
13728
  async getTodaySpending() {
13462
- const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13463
- if (!existsSync22(ledgerPath))
13729
+ const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
13730
+ if (!existsSync23(ledgerPath))
13464
13731
  return 0;
13465
13732
  try {
13466
13733
  const todayPrefix = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -13503,8 +13770,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13503
13770
  if (todaySpent + amountUsdc > budget.dailyLimitUsdc) {
13504
13771
  return { allowed: false, reason: `Would exceed daily limit ($${((todaySpent + amountUsdc) / 1e6).toFixed(6)} > $${(budget.dailyLimitUsdc / 1e6).toFixed(6)})` };
13505
13772
  }
13506
- const walletPath = join29(this.nexusDir, "wallet.enc");
13507
- if (existsSync22(walletPath)) {
13773
+ const walletPath = join30(this.nexusDir, "wallet.enc");
13774
+ if (existsSync23(walletPath)) {
13508
13775
  try {
13509
13776
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
13510
13777
  if (w.version === 2 && w.address) {
@@ -13534,8 +13801,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13534
13801
  const budgetResult = await this.checkBudget(amountSmallest, "transfer:direct", targetAddress);
13535
13802
  if (!budgetResult.allowed)
13536
13803
  return `BLOCKED by budget policy: ${budgetResult.reason}`;
13537
- const walletPath = join29(this.nexusDir, "wallet.enc");
13538
- if (!existsSync22(walletPath))
13804
+ const walletPath = join30(this.nexusDir, "wallet.enc");
13805
+ if (!existsSync23(walletPath))
13539
13806
  throw new Error("No wallet. Use wallet_create first.");
13540
13807
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
13541
13808
  if (!w.encryptedKey)
@@ -13595,7 +13862,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13595
13862
  capability: "transfer:direct",
13596
13863
  note: "signed, awaiting submission"
13597
13864
  });
13598
- const proofFile = join29(this.nexusDir, "pending-transfer.json");
13865
+ const proofFile = join30(this.nexusDir, "pending-transfer.json");
13599
13866
  const proof = {
13600
13867
  from: account.address,
13601
13868
  to: targetAddress,
@@ -13637,8 +13904,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13637
13904
  throw new Error("prompt is required");
13638
13905
  const estimatedTokens = Math.ceil(prompt.length / 4) + 1e3;
13639
13906
  let estimatedCostSmallest = 0;
13640
- const pricingPath = join29(this.nexusDir, "pricing.json");
13641
- if (existsSync22(pricingPath)) {
13907
+ const pricingPath = join30(this.nexusDir, "pricing.json");
13908
+ if (existsSync23(pricingPath)) {
13642
13909
  try {
13643
13910
  const pricing = JSON.parse(await readFile13(pricingPath, "utf8"));
13644
13911
  const modelPricing = (pricing.models || []).find((m) => m.model === model || m.model.startsWith(model.split(":")[0]));
@@ -13757,7 +14024,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13757
14024
  const bar = (s) => "\u2588".repeat(Math.round(s / 5)) + "\u2591".repeat(20 - Math.round(s / 5));
13758
14025
  const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
13759
14026
  await this.ensureDir();
13760
- await writeFile12(join29(this.nexusDir, "inference-proof.json"), JSON.stringify({
14027
+ await writeFile12(join30(this.nexusDir, "inference-proof.json"), JSON.stringify({
13761
14028
  modelName,
13762
14029
  gpuName,
13763
14030
  vramMb,
@@ -13885,6 +14152,7 @@ var init_dist2 = __esm({
13885
14152
  init_custom_tool();
13886
14153
  init_tool_creator();
13887
14154
  init_skill_tools();
14155
+ init_skill_builder();
13888
14156
  init_transcribe_tool();
13889
14157
  init_structured_file();
13890
14158
  init_code_sandbox();
@@ -14587,30 +14855,30 @@ var init_dist3 = __esm({
14587
14855
  });
14588
14856
 
14589
14857
  // packages/orchestrator/dist/promptLoader.js
14590
- import { readFileSync as readFileSync16, existsSync as existsSync23 } from "node:fs";
14591
- import { join as join30, dirname as dirname10 } from "node:path";
14858
+ import { readFileSync as readFileSync17, existsSync as existsSync24 } from "node:fs";
14859
+ import { join as join31, dirname as dirname11 } from "node:path";
14592
14860
  import { fileURLToPath as fileURLToPath7 } from "node:url";
14593
14861
  function loadPrompt(promptPath, vars) {
14594
14862
  let content = cache.get(promptPath);
14595
14863
  if (content === void 0) {
14596
- const fullPath = join30(PROMPTS_DIR, promptPath);
14597
- if (!existsSync23(fullPath)) {
14864
+ const fullPath = join31(PROMPTS_DIR, promptPath);
14865
+ if (!existsSync24(fullPath)) {
14598
14866
  throw new Error(`Prompt file not found: ${fullPath}`);
14599
14867
  }
14600
- content = readFileSync16(fullPath, "utf-8");
14868
+ content = readFileSync17(fullPath, "utf-8");
14601
14869
  cache.set(promptPath, content);
14602
14870
  }
14603
14871
  if (!vars)
14604
14872
  return content;
14605
14873
  return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
14606
14874
  }
14607
- var __filename, __dirname3, PROMPTS_DIR, cache;
14875
+ var __filename, __dirname4, PROMPTS_DIR, cache;
14608
14876
  var init_promptLoader = __esm({
14609
14877
  "packages/orchestrator/dist/promptLoader.js"() {
14610
14878
  "use strict";
14611
14879
  __filename = fileURLToPath7(import.meta.url);
14612
- __dirname3 = dirname10(__filename);
14613
- PROMPTS_DIR = join30(__dirname3, "..", "prompts");
14880
+ __dirname4 = dirname11(__filename);
14881
+ PROMPTS_DIR = join31(__dirname4, "..", "prompts");
14614
14882
  cache = /* @__PURE__ */ new Map();
14615
14883
  }
14616
14884
  });
@@ -14990,7 +15258,7 @@ var init_code_retriever = __esm({
14990
15258
  import { execFile as execFile5 } from "node:child_process";
14991
15259
  import { promisify as promisify4 } from "node:util";
14992
15260
  import { readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
14993
- import { join as join31, extname as extname7 } from "node:path";
15261
+ import { join as join32, extname as extname7 } from "node:path";
14994
15262
  async function searchByPath(pathPattern, options) {
14995
15263
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
14996
15264
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -15132,7 +15400,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
15132
15400
  continue;
15133
15401
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
15134
15402
  continue;
15135
- const absPath = join31(dir, entry.name);
15403
+ const absPath = join32(dir, entry.name);
15136
15404
  if (entry.isDirectory()) {
15137
15405
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
15138
15406
  } else if (entry.isFile()) {
@@ -15439,7 +15707,7 @@ var init_graphExpand = __esm({
15439
15707
 
15440
15708
  // packages/retrieval/dist/snippetPacker.js
15441
15709
  import { readFile as readFile15 } from "node:fs/promises";
15442
- import { join as join32 } from "node:path";
15710
+ import { join as join33 } from "node:path";
15443
15711
  async function packSnippets(requests, opts = {}) {
15444
15712
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
15445
15713
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -15465,7 +15733,7 @@ async function packSnippets(requests, opts = {}) {
15465
15733
  return { packed, dropped, totalTokens };
15466
15734
  }
15467
15735
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
15468
- const absPath = req.filePath.startsWith("/") ? req.filePath : join32(repoRoot, req.filePath);
15736
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join33(repoRoot, req.filePath);
15469
15737
  let content;
15470
15738
  try {
15471
15739
  content = await readFile15(absPath, "utf-8");
@@ -16646,6 +16914,7 @@ var init_agenticRunner = __esm({
16646
16914
  _sudoPassword = null;
16647
16915
  _sudoResolve = null;
16648
16916
  _pendingCompaction = null;
16917
+ _skillCompactionStrategy = null;
16649
16918
  // -- Task State Tracking (Priority 3) --
16650
16919
  _taskState = {
16651
16920
  goal: "",
@@ -16713,6 +16982,54 @@ var init_agenticRunner = __esm({
16713
16982
  }));
16714
16983
  }
16715
16984
  // -------------------------------------------------------------------------
16985
+ // Structured Context Assembly — C = A(c_instr, c_know, c_tools, c_mem, c_state, c_query)
16986
+ // Reference: "A Survey of Context Engineering for LLMs" (arXiv:2507.xxxxx)
16987
+ // -------------------------------------------------------------------------
16988
+ /**
16989
+ * Assemble context from multiple sources into a structured system prompt.
16990
+ * Each section is labeled with its role in the context engineering equation
16991
+ * and tracked for token budget analysis.
16992
+ *
16993
+ * Instruction hierarchy (arXiv:2404.13208):
16994
+ * - Priority 0: c_instr (system instructions — immutable rules)
16995
+ * - Priority 10: c_state (personality, project context)
16996
+ * - Priority 20: c_know (retrieved knowledge, dynamic context)
16997
+ * - Priority 30: c_tools (tool definitions — handled separately by API)
16998
+ */
16999
+ assembleContext(task, context) {
17000
+ const sections = [];
17001
+ const basePrompt = getSystemPromptForTier(this.options.modelTier);
17002
+ sections.push({
17003
+ label: "c_instr",
17004
+ content: basePrompt,
17005
+ tokenEstimate: Math.ceil(basePrompt.length / 4)
17006
+ });
17007
+ const personalitySuffix = this.options.personality ? compilePersonalityPrompt(this.options.personality) : "";
17008
+ if (personalitySuffix) {
17009
+ sections.push({
17010
+ label: "c_state",
17011
+ content: personalitySuffix,
17012
+ tokenEstimate: Math.ceil(personalitySuffix.length / 4)
17013
+ });
17014
+ }
17015
+ if (this.options.dynamicContext) {
17016
+ sections.push({
17017
+ label: "c_know",
17018
+ content: `
17019
+
17020
+ ${this.options.dynamicContext}`,
17021
+ tokenEstimate: Math.ceil(this.options.dynamicContext.length / 4)
17022
+ });
17023
+ }
17024
+ const assembled = sections.map((s) => s.content).join("");
17025
+ const totalTokenEstimate = sections.reduce((sum, s) => sum + s.tokenEstimate, 0);
17026
+ return {
17027
+ assembled,
17028
+ sections: sections.map((s) => ({ label: s.label, tokenEstimate: s.tokenEstimate })),
17029
+ totalTokenEstimate
17030
+ };
17031
+ }
17032
+ // -------------------------------------------------------------------------
16716
17033
  // Context-aware limits — all dynamic values derived from contextWindowSize
16717
17034
  // and modelTier. Call this instead of using hardcoded magic numbers.
16718
17035
  // -------------------------------------------------------------------------
@@ -16844,6 +17161,14 @@ var init_agenticRunner = __esm({
16844
17161
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
16845
17162
  });
16846
17163
  }
17164
+ /**
17165
+ * Set the active skill's preferred compaction strategy.
17166
+ * When set, auto-compaction uses this strategy instead of "default".
17167
+ * Called by the CLI when a skill is loaded via skill_execute.
17168
+ */
17169
+ setSkillCompactionStrategy(strategy) {
17170
+ this._skillCompactionStrategy = strategy;
17171
+ }
16847
17172
  /**
16848
17173
  * If paused, block until resume() or abort() is called.
16849
17174
  * Returns true if the loop should continue, false if aborted while paused.
@@ -16921,12 +17246,13 @@ Respond with your assessment, then take action.`;
16921
17246
  this._fileRegistry.clear();
16922
17247
  this._memexArchive.clear();
16923
17248
  this._sessionId = `session-${Date.now()}`;
16924
- const basePrompt = getSystemPromptForTier(this.options.modelTier);
16925
- const personalitySuffix = this.options.personality ? compilePersonalityPrompt(this.options.personality) : "";
16926
- const promptWithPersonality = personalitySuffix ? `${basePrompt}${personalitySuffix}` : basePrompt;
16927
- const systemPrompt = this.options.dynamicContext ? `${promptWithPersonality}
16928
-
16929
- ${this.options.dynamicContext}` : promptWithPersonality;
17249
+ const contextComposition = this.assembleContext(task, context);
17250
+ const systemPrompt = contextComposition.assembled;
17251
+ this.emit({
17252
+ type: "status",
17253
+ content: `Context assembled: ${contextComposition.sections.map((s) => `${s.label}(${s.tokenEstimate}t)`).join(" + ")} = ~${contextComposition.totalTokenEstimate}t`,
17254
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
17255
+ });
16930
17256
  const messages = [
16931
17257
  { role: "system", content: systemPrompt },
16932
17258
  { role: "user", content: context ? `${context}
@@ -17294,7 +17620,7 @@ You have used ${totalTurns} turns and ${toolCallCount} tool calls so far. The ta
17294
17620
 
17295
17621
  You have ${this.options.maxTurns} more turns. Continue making progress. Call task_complete when the task is fully done.`
17296
17622
  });
17297
- const compacted = await this.compactMessages(messages);
17623
+ const compacted = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
17298
17624
  if (compacted !== messages) {
17299
17625
  messages.length = 0;
17300
17626
  messages.push(...compacted);
@@ -17358,7 +17684,7 @@ Integrate this guidance into your current approach. Continue working on the task
17358
17684
  this._pendingCompaction = null;
17359
17685
  compactedMsgs = await this.compactMessages(messages, strategy, true);
17360
17686
  } else {
17361
- compactedMsgs = await this.compactMessages(messages);
17687
+ compactedMsgs = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
17362
17688
  }
17363
17689
  const chatRequest = { messages: compactedMsgs, tools: toolDefs, temperature: this.options.temperature, maxTokens: this.options.maxTokens, timeoutMs: this.options.requestTimeoutMs };
17364
17690
  let response;
@@ -17636,10 +17962,10 @@ ${marker}` : marker);
17636
17962
  if (!this._workingDirectory)
17637
17963
  return;
17638
17964
  try {
17639
- const { mkdirSync: mkdirSync18, writeFileSync: writeFileSync16 } = __require("node:fs");
17640
- const { join: join53 } = __require("node:path");
17641
- const sessionDir = join53(this._workingDirectory, ".oa", "session", this._sessionId);
17642
- mkdirSync18(sessionDir, { recursive: true });
17965
+ const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync17 } = __require("node:fs");
17966
+ const { join: join54 } = __require("node:path");
17967
+ const sessionDir = join54(this._workingDirectory, ".oa", "session", this._sessionId);
17968
+ mkdirSync19(sessionDir, { recursive: true });
17643
17969
  const checkpoint = {
17644
17970
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
17645
17971
  sessionId: this._sessionId,
@@ -17651,7 +17977,7 @@ ${marker}` : marker);
17651
17977
  memexEntryCount: this._memexArchive.size,
17652
17978
  fileRegistrySize: this._fileRegistry.size
17653
17979
  };
17654
- writeFileSync16(join53(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17980
+ writeFileSync17(join54(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17655
17981
  } catch {
17656
17982
  }
17657
17983
  }
@@ -17943,6 +18269,7 @@ ${newerSummary}` : newerSummary;
17943
18269
  const commandResults = [];
17944
18270
  const searchFindings = [];
17945
18271
  const errors = [];
18272
+ let skillResults;
17946
18273
  let toolCallCount = 0;
17947
18274
  for (const msg of messages) {
17948
18275
  if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.trim()) {
@@ -18036,6 +18363,19 @@ ${newerSummary}` : newerSummary;
18036
18363
  searchFindings.push(`find "${pattern}": ${files.length} files \u2014 ${files.slice(0, 5).join(", ")}`);
18037
18364
  break;
18038
18365
  }
18366
+ case "skill_build":
18367
+ case "skill_execute":
18368
+ case "skill_list":
18369
+ case "memory_write":
18370
+ case "memory_read": {
18371
+ const summary = content.length > 300 ? content.slice(0, 300) + "..." : content;
18372
+ if (!skillResults)
18373
+ skillResults = [];
18374
+ skillResults.push(`${tc.name}: ${summary}`);
18375
+ if (content.startsWith("Error:"))
18376
+ errors.push(`${tc.name}: ${content.slice(0, 200)}`);
18377
+ break;
18378
+ }
18039
18379
  default: {
18040
18380
  if (content.startsWith("Error:"))
18041
18381
  errors.push(`${tc.name}: ${content.slice(0, 200)}`);
@@ -18084,6 +18424,13 @@ ${newerSummary}` : newerSummary;
18084
18424
  }
18085
18425
  parts.push("");
18086
18426
  }
18427
+ if (skillResults && skillResults.length > 0) {
18428
+ parts.push("### Skill/Memory Context");
18429
+ for (const sr of skillResults.slice(0, 5)) {
18430
+ parts.push(`- ${sr}`);
18431
+ }
18432
+ parts.push("");
18433
+ }
18087
18434
  if (errors.length > 0) {
18088
18435
  parts.push("### Errors Encountered");
18089
18436
  for (const error of errors.slice(0, 5)) {
@@ -18261,11 +18608,24 @@ ${newerSummary}` : newerSummary;
18261
18608
  context: action,
18262
18609
  error: content.slice(0, 300)
18263
18610
  });
18611
+ } else if (tc.name === "skill_build" || tc.name === "skill_execute" || tc.name === "memory_read") {
18612
+ successes.push(`${action}: ${content.slice(0, 200)}`);
18264
18613
  } else {
18265
18614
  successes.push(`${action} \u2192 ok`);
18266
18615
  }
18267
18616
  }
18268
18617
  }
18618
+ const decisions = [];
18619
+ for (const msg of messages) {
18620
+ if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.trim().length > 30) {
18621
+ const decisionPatterns = /(?:I (?:will|need to|should|decided|chose|'ll)|Let me|The (?:fix|solution|approach|issue))[^.!?\n]{10,120}[.!?]/gi;
18622
+ const matches = msg.content.match(decisionPatterns);
18623
+ if (matches) {
18624
+ for (const m of matches.slice(0, 2))
18625
+ decisions.push(m.trim());
18626
+ }
18627
+ }
18628
+ }
18269
18629
  const parts = [];
18270
18630
  parts.push(`## Error-Focused Compact
18271
18631
  `);
@@ -18279,6 +18639,12 @@ ${newerSummary}` : newerSummary;
18279
18639
  }
18280
18640
  parts.push("");
18281
18641
  }
18642
+ if (decisions.length > 0) {
18643
+ parts.push("### Key Decisions");
18644
+ for (const d of decisions.slice(0, 5))
18645
+ parts.push(`- ${d}`);
18646
+ parts.push("");
18647
+ }
18282
18648
  if (successes.length > 0) {
18283
18649
  parts.push(`### Successful Operations (${successes.length} total)`);
18284
18650
  for (const s of successes.slice(0, 10))
@@ -19429,8 +19795,8 @@ __export(listen_exports, {
19429
19795
  waitForTranscribeCli: () => waitForTranscribeCli
19430
19796
  });
19431
19797
  import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
19432
- import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
19433
- import { join as join33, dirname as dirname11 } from "node:path";
19798
+ import { existsSync as existsSync25, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readdirSync as readdirSync6 } from "node:fs";
19799
+ import { join as join34, dirname as dirname12 } from "node:path";
19434
19800
  import { homedir as homedir8 } from "node:os";
19435
19801
  import { fileURLToPath as fileURLToPath8 } from "node:url";
19436
19802
  import { EventEmitter } from "node:events";
@@ -19514,17 +19880,17 @@ function findMicCaptureCommand() {
19514
19880
  return null;
19515
19881
  }
19516
19882
  function findLiveWhisperScript() {
19517
- const thisDir = dirname11(fileURLToPath8(import.meta.url));
19883
+ const thisDir = dirname12(fileURLToPath8(import.meta.url));
19518
19884
  const candidates = [
19519
- join33(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
19520
- join33(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
19521
- join33(thisDir, "../../execution/scripts/live-whisper.py"),
19885
+ join34(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
19886
+ join34(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
19887
+ join34(thisDir, "../../execution/scripts/live-whisper.py"),
19522
19888
  // npm install layout — scripts bundled alongside dist
19523
- join33(thisDir, "../scripts/live-whisper.py"),
19524
- join33(thisDir, "../../scripts/live-whisper.py")
19889
+ join34(thisDir, "../scripts/live-whisper.py"),
19890
+ join34(thisDir, "../../scripts/live-whisper.py")
19525
19891
  ];
19526
19892
  for (const p of candidates) {
19527
- if (existsSync24(p))
19893
+ if (existsSync25(p))
19528
19894
  return p;
19529
19895
  }
19530
19896
  try {
@@ -19534,21 +19900,21 @@ function findLiveWhisperScript() {
19534
19900
  stdio: ["pipe", "pipe", "pipe"]
19535
19901
  }).trim();
19536
19902
  const candidates2 = [
19537
- join33(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
19538
- join33(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
19903
+ join34(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
19904
+ join34(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
19539
19905
  ];
19540
19906
  for (const p of candidates2) {
19541
- if (existsSync24(p))
19907
+ if (existsSync25(p))
19542
19908
  return p;
19543
19909
  }
19544
19910
  } catch {
19545
19911
  }
19546
- const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19547
- if (existsSync24(nvmBase)) {
19912
+ const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
19913
+ if (existsSync25(nvmBase)) {
19548
19914
  try {
19549
19915
  for (const ver of readdirSync6(nvmBase)) {
19550
- const p = join33(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19551
- if (existsSync24(p))
19916
+ const p = join34(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19917
+ if (existsSync25(p))
19552
19918
  return p;
19553
19919
  }
19554
19920
  } catch {
@@ -19566,7 +19932,7 @@ function ensureTranscribeCliBackground() {
19566
19932
  timeout: 5e3,
19567
19933
  stdio: ["pipe", "pipe", "pipe"]
19568
19934
  }).trim();
19569
- if (existsSync24(join33(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19935
+ if (existsSync25(join34(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19570
19936
  return true;
19571
19937
  }
19572
19938
  } catch {
@@ -19789,24 +20155,24 @@ var init_listen = __esm({
19789
20155
  timeout: 5e3,
19790
20156
  stdio: ["pipe", "pipe", "pipe"]
19791
20157
  }).trim();
19792
- const tcPath = join33(globalRoot, "transcribe-cli");
19793
- if (existsSync24(join33(tcPath, "dist", "index.js"))) {
20158
+ const tcPath = join34(globalRoot, "transcribe-cli");
20159
+ if (existsSync25(join34(tcPath, "dist", "index.js"))) {
19794
20160
  const { createRequire: createRequire4 } = await import("node:module");
19795
20161
  const req = createRequire4(import.meta.url);
19796
- return req(join33(tcPath, "dist", "index.js"));
20162
+ return req(join34(tcPath, "dist", "index.js"));
19797
20163
  }
19798
20164
  } catch {
19799
20165
  }
19800
- const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19801
- if (existsSync24(nvmBase)) {
20166
+ const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
20167
+ if (existsSync25(nvmBase)) {
19802
20168
  try {
19803
20169
  const { readdirSync: readdirSync15 } = await import("node:fs");
19804
20170
  for (const ver of readdirSync15(nvmBase)) {
19805
- const tcPath = join33(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
19806
- if (existsSync24(join33(tcPath, "dist", "index.js"))) {
20171
+ const tcPath = join34(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
20172
+ if (existsSync25(join34(tcPath, "dist", "index.js"))) {
19807
20173
  const { createRequire: createRequire4 } = await import("node:module");
19808
20174
  const req = createRequire4(import.meta.url);
19809
- return req(join33(tcPath, "dist", "index.js"));
20175
+ return req(join34(tcPath, "dist", "index.js"));
19810
20176
  }
19811
20177
  }
19812
20178
  } catch {
@@ -20088,10 +20454,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
20088
20454
  });
20089
20455
  if (outputDir) {
20090
20456
  const { basename: basename16 } = await import("node:path");
20091
- const transcriptDir = join33(outputDir, ".oa", "transcripts");
20092
- mkdirSync6(transcriptDir, { recursive: true });
20093
- const outFile = join33(transcriptDir, `${basename16(filePath)}.txt`);
20094
- writeFileSync6(outFile, result.text, "utf-8");
20457
+ const transcriptDir = join34(outputDir, ".oa", "transcripts");
20458
+ mkdirSync7(transcriptDir, { recursive: true });
20459
+ const outFile = join34(transcriptDir, `${basename16(filePath)}.txt`);
20460
+ writeFileSync7(outFile, result.text, "utf-8");
20095
20461
  }
20096
20462
  return {
20097
20463
  text: result.text,
@@ -24302,6 +24668,8 @@ function renderSlashHelp() {
24302
24668
  ["/nexus wallet", "Show wallet address and x402 payment status"],
24303
24669
  ["/style", "Show current response style"],
24304
24670
  ["/style <preset>", "Set style: concise, balanced, verbose, pedagogical"],
24671
+ ["/commands auto", "Allow agent to invoke slash commands as tools"],
24672
+ ["/commands manual", "Slash commands are user-only (default)"],
24305
24673
  ["/verbose", "Toggle verbose mode"],
24306
24674
  ["/clear", "Clear the screen"],
24307
24675
  ["/help", "Show this help"],
@@ -25689,8 +26057,8 @@ var init_types = __esm({
25689
26057
 
25690
26058
  // packages/cli/dist/tui/p2p/secret-vault.js
25691
26059
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
25692
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync25, mkdirSync as mkdirSync7 } from "node:fs";
25693
- import { join as join34, dirname as dirname12 } from "node:path";
26060
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync8, existsSync as existsSync26, mkdirSync as mkdirSync8 } from "node:fs";
26061
+ import { join as join35, dirname as dirname13 } from "node:path";
25694
26062
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
25695
26063
  var init_secret_vault = __esm({
25696
26064
  "packages/cli/dist/tui/p2p/secret-vault.js"() {
@@ -25901,19 +26269,19 @@ var init_secret_vault = __esm({
25901
26269
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
25902
26270
  const tag = cipher.getAuthTag();
25903
26271
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
25904
- const dir = dirname12(this.storePath);
25905
- if (!existsSync25(dir))
25906
- mkdirSync7(dir, { recursive: true });
25907
- writeFileSync7(this.storePath, blob, { mode: 384 });
26272
+ const dir = dirname13(this.storePath);
26273
+ if (!existsSync26(dir))
26274
+ mkdirSync8(dir, { recursive: true });
26275
+ writeFileSync8(this.storePath, blob, { mode: 384 });
25908
26276
  }
25909
26277
  /**
25910
26278
  * Load vault from disk, decrypting with the given passphrase.
25911
26279
  * Returns the number of secrets loaded.
25912
26280
  */
25913
26281
  load(passphrase) {
25914
- if (!this.storePath || !existsSync25(this.storePath))
26282
+ if (!this.storePath || !existsSync26(this.storePath))
25915
26283
  return 0;
25916
- const blob = readFileSync17(this.storePath);
26284
+ const blob = readFileSync18(this.storePath);
25917
26285
  if (blob.length < SALT_LEN + IV_LEN + 16) {
25918
26286
  throw new Error("Vault file is corrupted (too small)");
25919
26287
  }
@@ -27133,32 +27501,32 @@ var init_render2 = __esm({
27133
27501
  });
27134
27502
 
27135
27503
  // packages/prompts/dist/promptLoader.js
27136
- import { readFileSync as readFileSync18, existsSync as existsSync26 } from "node:fs";
27137
- import { join as join35, dirname as dirname13 } from "node:path";
27504
+ import { readFileSync as readFileSync19, existsSync as existsSync27 } from "node:fs";
27505
+ import { join as join36, dirname as dirname14 } from "node:path";
27138
27506
  import { fileURLToPath as fileURLToPath9 } from "node:url";
27139
27507
  function loadPrompt2(promptPath, vars) {
27140
27508
  let content = cache2.get(promptPath);
27141
27509
  if (content === void 0) {
27142
- const fullPath = join35(PROMPTS_DIR2, promptPath);
27143
- if (!existsSync26(fullPath)) {
27510
+ const fullPath = join36(PROMPTS_DIR2, promptPath);
27511
+ if (!existsSync27(fullPath)) {
27144
27512
  throw new Error(`Prompt file not found: ${fullPath}`);
27145
27513
  }
27146
- content = readFileSync18(fullPath, "utf-8");
27514
+ content = readFileSync19(fullPath, "utf-8");
27147
27515
  cache2.set(promptPath, content);
27148
27516
  }
27149
27517
  if (!vars)
27150
27518
  return content;
27151
27519
  return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
27152
27520
  }
27153
- var __filename2, __dirname4, devPath, publishedPath, PROMPTS_DIR2, cache2;
27521
+ var __filename2, __dirname5, devPath, publishedPath, PROMPTS_DIR2, cache2;
27154
27522
  var init_promptLoader2 = __esm({
27155
27523
  "packages/prompts/dist/promptLoader.js"() {
27156
27524
  "use strict";
27157
27525
  __filename2 = fileURLToPath9(import.meta.url);
27158
- __dirname4 = dirname13(__filename2);
27159
- devPath = join35(__dirname4, "..", "templates");
27160
- publishedPath = join35(__dirname4, "..", "prompts", "templates");
27161
- PROMPTS_DIR2 = existsSync26(devPath) ? devPath : publishedPath;
27526
+ __dirname5 = dirname14(__filename2);
27527
+ devPath = join36(__dirname5, "..", "templates");
27528
+ publishedPath = join36(__dirname5, "..", "prompts", "templates");
27529
+ PROMPTS_DIR2 = existsSync27(devPath) ? devPath : publishedPath;
27162
27530
  cache2 = /* @__PURE__ */ new Map();
27163
27531
  }
27164
27532
  });
@@ -27269,7 +27637,7 @@ var init_task_templates = __esm({
27269
27637
  });
27270
27638
 
27271
27639
  // packages/prompts/dist/index.js
27272
- import { join as join36, dirname as dirname14 } from "node:path";
27640
+ import { join as join37, dirname as dirname15 } from "node:path";
27273
27641
  import { fileURLToPath as fileURLToPath10 } from "node:url";
27274
27642
  var _dir, _packageRoot;
27275
27643
  var init_dist6 = __esm({
@@ -27279,27 +27647,27 @@ var init_dist6 = __esm({
27279
27647
  init_render2();
27280
27648
  init_task_templates();
27281
27649
  init_render2();
27282
- _dir = dirname14(fileURLToPath10(import.meta.url));
27283
- _packageRoot = join36(_dir, "..");
27650
+ _dir = dirname15(fileURLToPath10(import.meta.url));
27651
+ _packageRoot = join37(_dir, "..");
27284
27652
  }
27285
27653
  });
27286
27654
 
27287
27655
  // packages/cli/dist/tui/oa-directory.js
27288
- import { existsSync as existsSync27, mkdirSync as mkdirSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
27289
- import { join as join37, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
27656
+ import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync9, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
27657
+ import { join as join38, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
27290
27658
  import { homedir as homedir9 } from "node:os";
27291
27659
  function initOaDirectory(repoRoot) {
27292
- const oaPath = join37(repoRoot, OA_DIR);
27660
+ const oaPath = join38(repoRoot, OA_DIR);
27293
27661
  for (const sub of SUBDIRS) {
27294
- mkdirSync8(join37(oaPath, sub), { recursive: true });
27662
+ mkdirSync9(join38(oaPath, sub), { recursive: true });
27295
27663
  }
27296
27664
  try {
27297
- const gitignorePath = join37(repoRoot, ".gitignore");
27665
+ const gitignorePath = join38(repoRoot, ".gitignore");
27298
27666
  const settingsPattern = ".oa/settings.json";
27299
- if (existsSync27(gitignorePath)) {
27300
- const content = readFileSync19(gitignorePath, "utf-8");
27667
+ if (existsSync28(gitignorePath)) {
27668
+ const content = readFileSync20(gitignorePath, "utf-8");
27301
27669
  if (!content.includes(settingsPattern)) {
27302
- writeFileSync8(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
27670
+ writeFileSync9(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
27303
27671
  }
27304
27672
  }
27305
27673
  } catch {
@@ -27307,41 +27675,41 @@ function initOaDirectory(repoRoot) {
27307
27675
  return oaPath;
27308
27676
  }
27309
27677
  function hasOaDirectory(repoRoot) {
27310
- return existsSync27(join37(repoRoot, OA_DIR, "index"));
27678
+ return existsSync28(join38(repoRoot, OA_DIR, "index"));
27311
27679
  }
27312
27680
  function loadProjectSettings(repoRoot) {
27313
- const settingsPath = join37(repoRoot, OA_DIR, "settings.json");
27681
+ const settingsPath = join38(repoRoot, OA_DIR, "settings.json");
27314
27682
  try {
27315
- if (existsSync27(settingsPath)) {
27316
- return JSON.parse(readFileSync19(settingsPath, "utf-8"));
27683
+ if (existsSync28(settingsPath)) {
27684
+ return JSON.parse(readFileSync20(settingsPath, "utf-8"));
27317
27685
  }
27318
27686
  } catch {
27319
27687
  }
27320
27688
  return {};
27321
27689
  }
27322
27690
  function saveProjectSettings(repoRoot, settings) {
27323
- const oaPath = join37(repoRoot, OA_DIR);
27324
- mkdirSync8(oaPath, { recursive: true });
27691
+ const oaPath = join38(repoRoot, OA_DIR);
27692
+ mkdirSync9(oaPath, { recursive: true });
27325
27693
  const existing = loadProjectSettings(repoRoot);
27326
27694
  const merged = { ...existing, ...settings };
27327
- writeFileSync8(join37(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27695
+ writeFileSync9(join38(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27328
27696
  }
27329
27697
  function loadGlobalSettings() {
27330
- const settingsPath = join37(homedir9(), ".open-agents", "settings.json");
27698
+ const settingsPath = join38(homedir9(), ".open-agents", "settings.json");
27331
27699
  try {
27332
- if (existsSync27(settingsPath)) {
27333
- return JSON.parse(readFileSync19(settingsPath, "utf-8"));
27700
+ if (existsSync28(settingsPath)) {
27701
+ return JSON.parse(readFileSync20(settingsPath, "utf-8"));
27334
27702
  }
27335
27703
  } catch {
27336
27704
  }
27337
27705
  return {};
27338
27706
  }
27339
27707
  function saveGlobalSettings(settings) {
27340
- const dir = join37(homedir9(), ".open-agents");
27341
- mkdirSync8(dir, { recursive: true });
27708
+ const dir = join38(homedir9(), ".open-agents");
27709
+ mkdirSync9(dir, { recursive: true });
27342
27710
  const existing = loadGlobalSettings();
27343
27711
  const merged = { ...existing, ...settings };
27344
- writeFileSync8(join37(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27712
+ writeFileSync9(join38(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27345
27713
  }
27346
27714
  function resolveSettings(repoRoot) {
27347
27715
  const global = loadGlobalSettings();
@@ -27356,12 +27724,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27356
27724
  while (dir && !visited.has(dir)) {
27357
27725
  visited.add(dir);
27358
27726
  for (const name of CONTEXT_FILES) {
27359
- const filePath = join37(dir, name);
27727
+ const filePath = join38(dir, name);
27360
27728
  const normalizedName = name.toLowerCase();
27361
- if (existsSync27(filePath) && !seen.has(filePath)) {
27729
+ if (existsSync28(filePath) && !seen.has(filePath)) {
27362
27730
  seen.add(filePath);
27363
27731
  try {
27364
- let content = readFileSync19(filePath, "utf-8");
27732
+ let content = readFileSync20(filePath, "utf-8");
27365
27733
  if (content.length > maxContentLen) {
27366
27734
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
27367
27735
  }
@@ -27375,11 +27743,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27375
27743
  }
27376
27744
  }
27377
27745
  }
27378
- const projectMap = join37(dir, OA_DIR, "context", "project-map.md");
27379
- if (existsSync27(projectMap) && !seen.has(projectMap)) {
27746
+ const projectMap = join38(dir, OA_DIR, "context", "project-map.md");
27747
+ if (existsSync28(projectMap) && !seen.has(projectMap)) {
27380
27748
  seen.add(projectMap);
27381
27749
  try {
27382
- let content = readFileSync19(projectMap, "utf-8");
27750
+ let content = readFileSync20(projectMap, "utf-8");
27383
27751
  if (content.length > maxContentLen) {
27384
27752
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
27385
27753
  }
@@ -27391,7 +27759,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27391
27759
  } catch {
27392
27760
  }
27393
27761
  }
27394
- const parent = join37(dir, "..");
27762
+ const parent = join38(dir, "..");
27395
27763
  if (parent === dir)
27396
27764
  break;
27397
27765
  dir = parent;
@@ -27409,9 +27777,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27409
27777
  return found;
27410
27778
  }
27411
27779
  function readIndexMeta(repoRoot) {
27412
- const metaPath = join37(repoRoot, OA_DIR, "index", "meta.json");
27780
+ const metaPath = join38(repoRoot, OA_DIR, "index", "meta.json");
27413
27781
  try {
27414
- return JSON.parse(readFileSync19(metaPath, "utf-8"));
27782
+ return JSON.parse(readFileSync20(metaPath, "utf-8"));
27415
27783
  } catch {
27416
27784
  return null;
27417
27785
  }
@@ -27462,28 +27830,28 @@ ${tree}\`\`\`
27462
27830
  sections.push("");
27463
27831
  }
27464
27832
  const content = sections.join("\n");
27465
- const contextDir = join37(repoRoot, OA_DIR, "context");
27466
- mkdirSync8(contextDir, { recursive: true });
27467
- writeFileSync8(join37(contextDir, "project-map.md"), content, "utf-8");
27833
+ const contextDir = join38(repoRoot, OA_DIR, "context");
27834
+ mkdirSync9(contextDir, { recursive: true });
27835
+ writeFileSync9(join38(contextDir, "project-map.md"), content, "utf-8");
27468
27836
  return content;
27469
27837
  }
27470
27838
  function saveSession(repoRoot, session) {
27471
- const historyDir = join37(repoRoot, OA_DIR, "history");
27472
- mkdirSync8(historyDir, { recursive: true });
27473
- writeFileSync8(join37(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
27839
+ const historyDir = join38(repoRoot, OA_DIR, "history");
27840
+ mkdirSync9(historyDir, { recursive: true });
27841
+ writeFileSync9(join38(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
27474
27842
  }
27475
27843
  function loadRecentSessions(repoRoot, limit = 5) {
27476
- const historyDir = join37(repoRoot, OA_DIR, "history");
27477
- if (!existsSync27(historyDir))
27844
+ const historyDir = join38(repoRoot, OA_DIR, "history");
27845
+ if (!existsSync28(historyDir))
27478
27846
  return [];
27479
27847
  try {
27480
27848
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
27481
- const stat5 = statSync9(join37(historyDir, f));
27849
+ const stat5 = statSync9(join38(historyDir, f));
27482
27850
  return { file: f, mtime: stat5.mtimeMs };
27483
27851
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
27484
27852
  return files.map((f) => {
27485
27853
  try {
27486
- return JSON.parse(readFileSync19(join37(historyDir, f.file), "utf-8"));
27854
+ return JSON.parse(readFileSync20(join38(historyDir, f.file), "utf-8"));
27487
27855
  } catch {
27488
27856
  return null;
27489
27857
  }
@@ -27493,16 +27861,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
27493
27861
  }
27494
27862
  }
27495
27863
  function savePendingTask(repoRoot, task) {
27496
- const historyDir = join37(repoRoot, OA_DIR, "history");
27497
- mkdirSync8(historyDir, { recursive: true });
27498
- writeFileSync8(join37(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
27864
+ const historyDir = join38(repoRoot, OA_DIR, "history");
27865
+ mkdirSync9(historyDir, { recursive: true });
27866
+ writeFileSync9(join38(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
27499
27867
  }
27500
27868
  function loadPendingTask(repoRoot) {
27501
- const filePath = join37(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27869
+ const filePath = join38(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27502
27870
  try {
27503
- if (!existsSync27(filePath))
27871
+ if (!existsSync28(filePath))
27504
27872
  return null;
27505
- const data = JSON.parse(readFileSync19(filePath, "utf-8"));
27873
+ const data = JSON.parse(readFileSync20(filePath, "utf-8"));
27506
27874
  try {
27507
27875
  unlinkSync3(filePath);
27508
27876
  } catch {
@@ -27513,13 +27881,13 @@ function loadPendingTask(repoRoot) {
27513
27881
  }
27514
27882
  }
27515
27883
  function saveSessionContext(repoRoot, entry) {
27516
- const contextDir = join37(repoRoot, OA_DIR, "context");
27517
- mkdirSync8(contextDir, { recursive: true });
27518
- const filePath = join37(contextDir, CONTEXT_SAVE_FILE);
27884
+ const contextDir = join38(repoRoot, OA_DIR, "context");
27885
+ mkdirSync9(contextDir, { recursive: true });
27886
+ const filePath = join38(contextDir, CONTEXT_SAVE_FILE);
27519
27887
  let ctx;
27520
27888
  try {
27521
- if (existsSync27(filePath)) {
27522
- ctx = JSON.parse(readFileSync19(filePath, "utf-8"));
27889
+ if (existsSync28(filePath)) {
27890
+ ctx = JSON.parse(readFileSync20(filePath, "utf-8"));
27523
27891
  } else {
27524
27892
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
27525
27893
  }
@@ -27531,14 +27899,14 @@ function saveSessionContext(repoRoot, entry) {
27531
27899
  ctx.entries = ctx.entries.slice(-ctx.maxEntries);
27532
27900
  }
27533
27901
  ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
27534
- writeFileSync8(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
27902
+ writeFileSync9(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
27535
27903
  }
27536
27904
  function loadSessionContext(repoRoot) {
27537
- const filePath = join37(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27905
+ const filePath = join38(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27538
27906
  try {
27539
- if (!existsSync27(filePath))
27907
+ if (!existsSync28(filePath))
27540
27908
  return null;
27541
- return JSON.parse(readFileSync19(filePath, "utf-8"));
27909
+ return JSON.parse(readFileSync20(filePath, "utf-8"));
27542
27910
  } catch {
27543
27911
  return null;
27544
27912
  }
@@ -27585,12 +27953,12 @@ function detectManifests(repoRoot) {
27585
27953
  { file: "docker-compose.yaml", type: "Docker Compose" }
27586
27954
  ];
27587
27955
  for (const check of checks) {
27588
- const filePath = join37(repoRoot, check.file);
27589
- if (existsSync27(filePath)) {
27956
+ const filePath = join38(repoRoot, check.file);
27957
+ if (existsSync28(filePath)) {
27590
27958
  let name;
27591
27959
  if (check.nameField) {
27592
27960
  try {
27593
- const data = JSON.parse(readFileSync19(filePath, "utf-8"));
27961
+ const data = JSON.parse(readFileSync20(filePath, "utf-8"));
27594
27962
  name = data[check.nameField];
27595
27963
  } catch {
27596
27964
  }
@@ -27619,7 +27987,7 @@ function findKeyFiles(repoRoot) {
27619
27987
  { pattern: "CLAUDE.md", description: "Claude Code context" }
27620
27988
  ];
27621
27989
  for (const check of checks) {
27622
- if (existsSync27(join37(repoRoot, check.pattern))) {
27990
+ if (existsSync28(join38(repoRoot, check.pattern))) {
27623
27991
  keyFiles.push({ path: check.pattern, description: check.description });
27624
27992
  }
27625
27993
  }
@@ -27645,12 +28013,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
27645
28013
  if (entry.isDirectory()) {
27646
28014
  let fileCount = 0;
27647
28015
  try {
27648
- fileCount = readdirSync7(join37(root, entry.name)).filter((f) => !f.startsWith(".")).length;
28016
+ fileCount = readdirSync7(join38(root, entry.name)).filter((f) => !f.startsWith(".")).length;
27649
28017
  } catch {
27650
28018
  }
27651
28019
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
27652
28020
  `;
27653
- result += buildDirTree(join37(root, entry.name), maxDepth, childPrefix, depth + 1);
28021
+ result += buildDirTree(join38(root, entry.name), maxDepth, childPrefix, depth + 1);
27654
28022
  } else if (depth < maxDepth) {
27655
28023
  result += `${prefix}${connector}${entry.name}
27656
28024
  `;
@@ -27704,8 +28072,8 @@ var init_oa_directory = __esm({
27704
28072
  // packages/cli/dist/tui/setup.js
27705
28073
  import * as readline from "node:readline";
27706
28074
  import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
27707
- import { existsSync as existsSync28, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
27708
- import { join as join38 } from "node:path";
28075
+ import { existsSync as existsSync29, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
28076
+ import { join as join39 } from "node:path";
27709
28077
  import { homedir as homedir10, platform } from "node:os";
27710
28078
  function detectSystemSpecs() {
27711
28079
  let totalRamGB = 0;
@@ -27938,7 +28306,7 @@ async function installOllamaMac(_rl) {
27938
28306
  execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
27939
28307
  if (!hasCmd("brew")) {
27940
28308
  try {
27941
- const brewPrefix = existsSync28("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
28309
+ const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
27942
28310
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
27943
28311
  } catch {
27944
28312
  }
@@ -28692,10 +29060,10 @@ async function doSetup(config, rl) {
28692
29060
  `PARAMETER num_predict ${numPredict}`,
28693
29061
  `PARAMETER stop "<|endoftext|>"`
28694
29062
  ].join("\n");
28695
- const modelDir2 = join38(homedir10(), ".open-agents", "models");
28696
- mkdirSync9(modelDir2, { recursive: true });
28697
- const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
28698
- writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
29063
+ const modelDir2 = join39(homedir10(), ".open-agents", "models");
29064
+ mkdirSync10(modelDir2, { recursive: true });
29065
+ const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
29066
+ writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
28699
29067
  process.stdout.write(` ${c2.dim("Creating model...")} `);
28700
29068
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
28701
29069
  stdio: "pipe",
@@ -28740,7 +29108,7 @@ async function isModelAvailable(config) {
28740
29108
  }
28741
29109
  function isFirstRun() {
28742
29110
  try {
28743
- return !existsSync28(join38(homedir10(), ".open-agents", "config.json"));
29111
+ return !existsSync29(join39(homedir10(), ".open-agents", "config.json"));
28744
29112
  } catch {
28745
29113
  return true;
28746
29114
  }
@@ -28777,7 +29145,7 @@ function detectPkgManager() {
28777
29145
  return null;
28778
29146
  }
28779
29147
  function getVenvDir() {
28780
- return join38(homedir10(), ".open-agents", "venv");
29148
+ return join39(homedir10(), ".open-agents", "venv");
28781
29149
  }
28782
29150
  function hasVenvModule() {
28783
29151
  try {
@@ -28789,8 +29157,8 @@ function hasVenvModule() {
28789
29157
  }
28790
29158
  function ensureVenv(log) {
28791
29159
  const venvDir = getVenvDir();
28792
- const venvPip = join38(venvDir, "bin", "pip");
28793
- if (existsSync28(venvPip))
29160
+ const venvPip = join39(venvDir, "bin", "pip");
29161
+ if (existsSync29(venvPip))
28794
29162
  return venvDir;
28795
29163
  log("Creating Python venv for vision deps...");
28796
29164
  if (!hasCmd("python3")) {
@@ -28802,9 +29170,9 @@ function ensureVenv(log) {
28802
29170
  return null;
28803
29171
  }
28804
29172
  try {
28805
- mkdirSync9(join38(homedir10(), ".open-agents"), { recursive: true });
29173
+ mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
28806
29174
  execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
28807
- execSync25(`"${join38(venvDir, "bin", "pip")}" install --upgrade pip`, {
29175
+ execSync25(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
28808
29176
  stdio: "pipe",
28809
29177
  timeout: 6e4
28810
29178
  });
@@ -29013,15 +29381,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29013
29381
  }
29014
29382
  }
29015
29383
  const venvDir = getVenvDir();
29016
- const venvBin = join38(venvDir, "bin");
29017
- const venvMoondream = join38(venvBin, "moondream-station");
29384
+ const venvBin = join39(venvDir, "bin");
29385
+ const venvMoondream = join39(venvBin, "moondream-station");
29018
29386
  const venv = ensureVenv(log);
29019
- if (venv && !hasCmd("moondream-station") && !existsSync28(venvMoondream)) {
29020
- const venvPip = join38(venvBin, "pip");
29387
+ if (venv && !hasCmd("moondream-station") && !existsSync29(venvMoondream)) {
29388
+ const venvPip = join39(venvBin, "pip");
29021
29389
  log("Installing moondream-station in ~/.open-agents/venv...");
29022
29390
  try {
29023
29391
  execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
29024
- if (existsSync28(venvMoondream)) {
29392
+ if (existsSync29(venvMoondream)) {
29025
29393
  log("moondream-station installed successfully.");
29026
29394
  } else {
29027
29395
  try {
@@ -29038,8 +29406,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29038
29406
  }
29039
29407
  }
29040
29408
  if (venv) {
29041
- const venvPython = join38(venvBin, "python");
29042
- const venvPip2 = join38(venvBin, "pip");
29409
+ const venvPython = join39(venvBin, "python");
29410
+ const venvPip2 = join39(venvBin, "pip");
29043
29411
  let ocrStackInstalled = false;
29044
29412
  try {
29045
29413
  execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
@@ -29152,10 +29520,10 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
29152
29520
  `PARAMETER num_predict ${numPredict}`,
29153
29521
  `PARAMETER stop "<|endoftext|>"`
29154
29522
  ].join("\n");
29155
- const modelDir2 = join38(homedir10(), ".open-agents", "models");
29156
- mkdirSync9(modelDir2, { recursive: true });
29157
- const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
29158
- writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
29523
+ const modelDir2 = join39(homedir10(), ".open-agents", "models");
29524
+ mkdirSync10(modelDir2, { recursive: true });
29525
+ const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
29526
+ writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
29159
29527
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
29160
29528
  stdio: "pipe",
29161
29529
  timeout: 12e4
@@ -29693,6 +30061,30 @@ async function handleSlashCommand(input, ctx) {
29693
30061
  }
29694
30062
  return "handled";
29695
30063
  }
30064
+ case "commands":
30065
+ case "cmds": {
30066
+ if (!ctx.getCommandsMode || !ctx.setCommandsMode) {
30067
+ renderWarning("Commands mode not available in this context.");
30068
+ return "handled";
30069
+ }
30070
+ if (arg === "auto") {
30071
+ ctx.setCommandsMode("auto");
30072
+ const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
30073
+ save({ commandsMode: "auto" });
30074
+ renderInfo("Commands mode: auto \u2014 the agent can now invoke slash commands as tools.");
30075
+ } else if (arg === "manual") {
30076
+ ctx.setCommandsMode("manual");
30077
+ const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
30078
+ save({ commandsMode: "manual" });
30079
+ renderInfo("Commands mode: manual \u2014 slash commands are user-only.");
30080
+ } else {
30081
+ const current = ctx.getCommandsMode();
30082
+ renderInfo(`Commands mode: ${c2.bold(current)}`);
30083
+ renderInfo(" /commands auto \u2014 agent can invoke slash commands as tools");
30084
+ renderInfo(" /commands manual \u2014 slash commands are user-only (default)");
30085
+ }
30086
+ return "handled";
30087
+ }
29696
30088
  case "dream": {
29697
30089
  if (arg === "stop" || arg === "wake") {
29698
30090
  if (ctx.isDreaming?.()) {
@@ -30459,17 +30851,17 @@ async function handleUpdate(subcommand, ctx) {
30459
30851
  try {
30460
30852
  const { createRequire: createRequire4 } = await import("node:module");
30461
30853
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
30462
- const { dirname: dirname18, join: join53 } = await import("node:path");
30463
- const { existsSync: existsSync39 } = await import("node:fs");
30854
+ const { dirname: dirname19, join: join54 } = await import("node:path");
30855
+ const { existsSync: existsSync40 } = await import("node:fs");
30464
30856
  const req = createRequire4(import.meta.url);
30465
- const thisDir = dirname18(fileURLToPath14(import.meta.url));
30857
+ const thisDir = dirname19(fileURLToPath14(import.meta.url));
30466
30858
  const candidates = [
30467
- join53(thisDir, "..", "package.json"),
30468
- join53(thisDir, "..", "..", "package.json"),
30469
- join53(thisDir, "..", "..", "..", "package.json")
30859
+ join54(thisDir, "..", "package.json"),
30860
+ join54(thisDir, "..", "..", "package.json"),
30861
+ join54(thisDir, "..", "..", "..", "package.json")
30470
30862
  ];
30471
30863
  for (const pkgPath of candidates) {
30472
- if (existsSync39(pkgPath)) {
30864
+ if (existsSync40(pkgPath)) {
30473
30865
  const pkg = req(pkgPath);
30474
30866
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
30475
30867
  currentVersion = pkg.version ?? "0.0.0";
@@ -30744,8 +31136,8 @@ var init_commands = __esm({
30744
31136
  });
30745
31137
 
30746
31138
  // packages/cli/dist/tui/project-context.js
30747
- import { existsSync as existsSync29, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
30748
- import { join as join39, basename as basename10 } from "node:path";
31139
+ import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
31140
+ import { join as join40, basename as basename10 } from "node:path";
30749
31141
  import { execSync as execSync26 } from "node:child_process";
30750
31142
  import { homedir as homedir11, platform as platform2, release } from "node:os";
30751
31143
  function getModelTier(modelName) {
@@ -30780,10 +31172,10 @@ function loadProjectMap(repoRoot) {
30780
31172
  if (!hasOaDirectory(repoRoot)) {
30781
31173
  initOaDirectory(repoRoot);
30782
31174
  }
30783
- const mapPath = join39(repoRoot, OA_DIR, "context", "project-map.md");
30784
- if (existsSync29(mapPath)) {
31175
+ const mapPath = join40(repoRoot, OA_DIR, "context", "project-map.md");
31176
+ if (existsSync30(mapPath)) {
30785
31177
  try {
30786
- const content = readFileSync20(mapPath, "utf-8");
31178
+ const content = readFileSync21(mapPath, "utf-8");
30787
31179
  return content;
30788
31180
  } catch {
30789
31181
  }
@@ -30824,31 +31216,31 @@ ${log}`);
30824
31216
  }
30825
31217
  function loadMemoryContext(repoRoot) {
30826
31218
  const sections = [];
30827
- const oaMemDir = join39(repoRoot, OA_DIR, "memory");
31219
+ const oaMemDir = join40(repoRoot, OA_DIR, "memory");
30828
31220
  const oaEntries = loadMemoryDir(oaMemDir, "project");
30829
31221
  if (oaEntries)
30830
31222
  sections.push(oaEntries);
30831
- const legacyMemDir = join39(repoRoot, ".open-agents", "memory");
30832
- if (legacyMemDir !== oaMemDir && existsSync29(legacyMemDir)) {
31223
+ const legacyMemDir = join40(repoRoot, ".open-agents", "memory");
31224
+ if (legacyMemDir !== oaMemDir && existsSync30(legacyMemDir)) {
30833
31225
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
30834
31226
  if (legacyEntries)
30835
31227
  sections.push(legacyEntries);
30836
31228
  }
30837
- const globalMemDir = join39(homedir11(), ".open-agents", "memory");
31229
+ const globalMemDir = join40(homedir11(), ".open-agents", "memory");
30838
31230
  const globalEntries = loadMemoryDir(globalMemDir, "global");
30839
31231
  if (globalEntries)
30840
31232
  sections.push(globalEntries);
30841
31233
  return sections.join("\n\n");
30842
31234
  }
30843
31235
  function loadMemoryDir(memDir, scope) {
30844
- if (!existsSync29(memDir))
31236
+ if (!existsSync30(memDir))
30845
31237
  return "";
30846
31238
  const lines = [];
30847
31239
  try {
30848
31240
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
30849
31241
  for (const file of files.slice(0, 10)) {
30850
31242
  try {
30851
- const raw = readFileSync20(join39(memDir, file), "utf-8");
31243
+ const raw = readFileSync21(join40(memDir, file), "utf-8");
30852
31244
  const entries = JSON.parse(raw);
30853
31245
  const topic = basename10(file, ".json");
30854
31246
  const keys = Object.keys(entries);
@@ -31875,22 +32267,22 @@ var init_carousel = __esm({
31875
32267
  });
31876
32268
 
31877
32269
  // packages/cli/dist/tui/carousel-descriptors.js
31878
- import { existsSync as existsSync30, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
31879
- import { join as join40, basename as basename11 } from "node:path";
32270
+ import { existsSync as existsSync31, readFileSync as readFileSync22, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
32271
+ import { join as join41, basename as basename11 } from "node:path";
31880
32272
  function loadToolProfile(repoRoot) {
31881
- const filePath = join40(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
32273
+ const filePath = join41(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
31882
32274
  try {
31883
- if (!existsSync30(filePath))
32275
+ if (!existsSync31(filePath))
31884
32276
  return null;
31885
- return JSON.parse(readFileSync21(filePath, "utf-8"));
32277
+ return JSON.parse(readFileSync22(filePath, "utf-8"));
31886
32278
  } catch {
31887
32279
  return null;
31888
32280
  }
31889
32281
  }
31890
32282
  function saveToolProfile(repoRoot, profile) {
31891
- const contextDir = join40(repoRoot, OA_DIR, "context");
31892
- mkdirSync10(contextDir, { recursive: true });
31893
- writeFileSync10(join40(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
32283
+ const contextDir = join41(repoRoot, OA_DIR, "context");
32284
+ mkdirSync11(contextDir, { recursive: true });
32285
+ writeFileSync11(join41(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
31894
32286
  }
31895
32287
  function categorizeToolCall(toolName) {
31896
32288
  for (const cat of TOOL_CATEGORIES) {
@@ -31948,25 +32340,25 @@ function weightedColor(profile) {
31948
32340
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
31949
32341
  }
31950
32342
  function loadCachedDescriptors(repoRoot) {
31951
- const filePath = join40(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
32343
+ const filePath = join41(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
31952
32344
  try {
31953
- if (!existsSync30(filePath))
32345
+ if (!existsSync31(filePath))
31954
32346
  return null;
31955
- const cached = JSON.parse(readFileSync21(filePath, "utf-8"));
32347
+ const cached = JSON.parse(readFileSync22(filePath, "utf-8"));
31956
32348
  return cached.phrases.length > 0 ? cached.phrases : null;
31957
32349
  } catch {
31958
32350
  return null;
31959
32351
  }
31960
32352
  }
31961
32353
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
31962
- const contextDir = join40(repoRoot, OA_DIR, "context");
31963
- mkdirSync10(contextDir, { recursive: true });
32354
+ const contextDir = join41(repoRoot, OA_DIR, "context");
32355
+ mkdirSync11(contextDir, { recursive: true });
31964
32356
  const cached = {
31965
32357
  phrases,
31966
32358
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
31967
32359
  sourceHash
31968
32360
  };
31969
- writeFileSync10(join40(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
32361
+ writeFileSync11(join41(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
31970
32362
  }
31971
32363
  function generateDescriptors(repoRoot) {
31972
32364
  const profile = loadToolProfile(repoRoot);
@@ -32014,11 +32406,11 @@ function generateDescriptors(repoRoot) {
32014
32406
  return phrases;
32015
32407
  }
32016
32408
  function extractFromPackageJson(repoRoot, tags) {
32017
- const pkgPath = join40(repoRoot, "package.json");
32409
+ const pkgPath = join41(repoRoot, "package.json");
32018
32410
  try {
32019
- if (!existsSync30(pkgPath))
32411
+ if (!existsSync31(pkgPath))
32020
32412
  return;
32021
- const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
32413
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
32022
32414
  if (pkg.name && typeof pkg.name === "string") {
32023
32415
  const parts = pkg.name.replace(/^@/, "").split("/");
32024
32416
  for (const p of parts)
@@ -32062,7 +32454,7 @@ function extractFromManifests(repoRoot, tags) {
32062
32454
  { file: ".github/workflows", tag: "ci/cd" }
32063
32455
  ];
32064
32456
  for (const check of manifestChecks) {
32065
- if (existsSync30(join40(repoRoot, check.file))) {
32457
+ if (existsSync31(join41(repoRoot, check.file))) {
32066
32458
  tags.push(check.tag);
32067
32459
  }
32068
32460
  }
@@ -32084,16 +32476,16 @@ function extractFromSessions(repoRoot, tags) {
32084
32476
  }
32085
32477
  }
32086
32478
  function extractFromMemory(repoRoot, tags) {
32087
- const memoryDir = join40(repoRoot, OA_DIR, "memory");
32479
+ const memoryDir = join41(repoRoot, OA_DIR, "memory");
32088
32480
  try {
32089
- if (!existsSync30(memoryDir))
32481
+ if (!existsSync31(memoryDir))
32090
32482
  return;
32091
32483
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
32092
32484
  for (const file of files) {
32093
32485
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
32094
32486
  tags.push(topic);
32095
32487
  try {
32096
- const data = JSON.parse(readFileSync21(join40(memoryDir, file), "utf-8"));
32488
+ const data = JSON.parse(readFileSync22(join41(memoryDir, file), "utf-8"));
32097
32489
  if (data && typeof data === "object") {
32098
32490
  const keys = Object.keys(data).slice(0, 3);
32099
32491
  for (const key of keys) {
@@ -32228,25 +32620,25 @@ var init_carousel_descriptors = __esm({
32228
32620
  });
32229
32621
 
32230
32622
  // packages/cli/dist/tui/voice.js
32231
- import { existsSync as existsSync31, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
32232
- import { join as join41 } from "node:path";
32623
+ import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
32624
+ import { join as join42 } from "node:path";
32233
32625
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
32234
32626
  import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
32235
32627
  import { createRequire } from "node:module";
32236
32628
  function voiceDir() {
32237
- return join41(homedir12(), ".open-agents", "voice");
32629
+ return join42(homedir12(), ".open-agents", "voice");
32238
32630
  }
32239
32631
  function modelsDir() {
32240
- return join41(voiceDir(), "models");
32632
+ return join42(voiceDir(), "models");
32241
32633
  }
32242
32634
  function modelDir(id) {
32243
- return join41(modelsDir(), id);
32635
+ return join42(modelsDir(), id);
32244
32636
  }
32245
32637
  function modelOnnxPath(id) {
32246
- return join41(modelDir(id), "model.onnx");
32638
+ return join42(modelDir(id), "model.onnx");
32247
32639
  }
32248
32640
  function modelConfigPath(id) {
32249
- return join41(modelDir(id), "config.json");
32641
+ return join42(modelDir(id), "config.json");
32250
32642
  }
32251
32643
  function emotionToPitchBias(emotion) {
32252
32644
  const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
@@ -33066,7 +33458,7 @@ var init_voice = __esm({
33066
33458
  }
33067
33459
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
33068
33460
  }
33069
- const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
33461
+ const wavPath = join42(tmpdir6(), `oa-voice-${Date.now()}.wav`);
33070
33462
  this.writeWav(audioData, sampleRate, wavPath);
33071
33463
  await this.playWav(wavPath);
33072
33464
  try {
@@ -33198,7 +33590,7 @@ var init_voice = __esm({
33198
33590
  return buffer;
33199
33591
  }
33200
33592
  writeWav(samples, sampleRate, path) {
33201
- writeFileSync11(path, this.buildWavBuffer(samples, sampleRate));
33593
+ writeFileSync12(path, this.buildWavBuffer(samples, sampleRate));
33202
33594
  }
33203
33595
  // -------------------------------------------------------------------------
33204
33596
  // Audio playback (system default speakers)
@@ -33357,7 +33749,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33357
33749
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
33358
33750
  const mlxVoice = model.mlxVoice ?? "af_heart";
33359
33751
  const mlxLangCode = model.mlxLangCode ?? "a";
33360
- const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
33752
+ const wavPath = join42(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
33361
33753
  const pyScript = [
33362
33754
  "import sys, json",
33363
33755
  "from mlx_audio.tts import generate as tts_gen",
@@ -33374,11 +33766,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33374
33766
  return;
33375
33767
  }
33376
33768
  }
33377
- if (!existsSync31(wavPath))
33769
+ if (!existsSync32(wavPath))
33378
33770
  return;
33379
33771
  if (volume !== 1) {
33380
33772
  try {
33381
- const wavData = readFileSync22(wavPath);
33773
+ const wavData = readFileSync23(wavPath);
33382
33774
  if (wavData.length > 44) {
33383
33775
  const header = wavData.subarray(0, 44);
33384
33776
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -33386,14 +33778,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33386
33778
  samples[i] = Math.round(samples[i] * volume);
33387
33779
  }
33388
33780
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
33389
- writeFileSync11(wavPath, scaled);
33781
+ writeFileSync12(wavPath, scaled);
33390
33782
  }
33391
33783
  } catch {
33392
33784
  }
33393
33785
  }
33394
33786
  if (this.onPCMOutput) {
33395
33787
  try {
33396
- const wavData = readFileSync22(wavPath);
33788
+ const wavData = readFileSync23(wavPath);
33397
33789
  if (wavData.length > 44) {
33398
33790
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
33399
33791
  const sampleRate = wavData.readUInt32LE(24);
@@ -33425,7 +33817,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33425
33817
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
33426
33818
  const mlxVoice = model.mlxVoice ?? "af_heart";
33427
33819
  const mlxLangCode = model.mlxLangCode ?? "a";
33428
- const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
33820
+ const wavPath = join42(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
33429
33821
  const pyScript = [
33430
33822
  "import sys, json",
33431
33823
  "from mlx_audio.tts import generate as tts_gen",
@@ -33442,10 +33834,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33442
33834
  return null;
33443
33835
  }
33444
33836
  }
33445
- if (!existsSync31(wavPath))
33837
+ if (!existsSync32(wavPath))
33446
33838
  return null;
33447
33839
  try {
33448
- const data = readFileSync22(wavPath);
33840
+ const data = readFileSync23(wavPath);
33449
33841
  unlinkSync4(wavPath);
33450
33842
  return data;
33451
33843
  } catch {
@@ -33459,41 +33851,41 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33459
33851
  if (this.ort)
33460
33852
  return;
33461
33853
  const arch = process.arch;
33462
- mkdirSync11(voiceDir(), { recursive: true });
33463
- const pkgPath = join41(voiceDir(), "package.json");
33854
+ mkdirSync12(voiceDir(), { recursive: true });
33855
+ const pkgPath = join42(voiceDir(), "package.json");
33464
33856
  const expectedDeps = {
33465
33857
  "onnxruntime-node": "^1.21.0",
33466
33858
  "phonemizer": "^1.2.1"
33467
33859
  };
33468
- if (existsSync31(pkgPath)) {
33860
+ if (existsSync32(pkgPath)) {
33469
33861
  try {
33470
- const existing = JSON.parse(readFileSync22(pkgPath, "utf8"));
33862
+ const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
33471
33863
  if (!existing.dependencies?.["phonemizer"]) {
33472
33864
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
33473
- writeFileSync11(pkgPath, JSON.stringify(existing, null, 2));
33865
+ writeFileSync12(pkgPath, JSON.stringify(existing, null, 2));
33474
33866
  }
33475
33867
  } catch {
33476
33868
  }
33477
33869
  }
33478
- if (!existsSync31(pkgPath)) {
33479
- writeFileSync11(pkgPath, JSON.stringify({
33870
+ if (!existsSync32(pkgPath)) {
33871
+ writeFileSync12(pkgPath, JSON.stringify({
33480
33872
  name: "open-agents-voice",
33481
33873
  private: true,
33482
33874
  dependencies: expectedDeps
33483
33875
  }, null, 2));
33484
33876
  }
33485
- const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
33877
+ const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
33486
33878
  const probeOnnx = () => {
33487
33879
  try {
33488
- const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join41(voiceDir(), "node_modules") } });
33880
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
33489
33881
  const output = result.toString().trim();
33490
33882
  return output === "OK";
33491
33883
  } catch {
33492
33884
  return false;
33493
33885
  }
33494
33886
  };
33495
- const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
33496
- const onnxInstalled = existsSync31(onnxNodeModules);
33887
+ const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
33888
+ const onnxInstalled = existsSync32(onnxNodeModules);
33497
33889
  if (onnxInstalled && !probeOnnx()) {
33498
33890
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
33499
33891
  }
@@ -33551,18 +33943,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33551
33943
  const dir = modelDir(id);
33552
33944
  const onnxPath = modelOnnxPath(id);
33553
33945
  const configPath = modelConfigPath(id);
33554
- if (existsSync31(onnxPath) && existsSync31(configPath))
33946
+ if (existsSync32(onnxPath) && existsSync32(configPath))
33555
33947
  return;
33556
- mkdirSync11(dir, { recursive: true });
33557
- if (!existsSync31(configPath)) {
33948
+ mkdirSync12(dir, { recursive: true });
33949
+ if (!existsSync32(configPath)) {
33558
33950
  renderInfo(`Downloading ${model.label} voice config...`);
33559
33951
  const configResp = await fetch(model.configUrl);
33560
33952
  if (!configResp.ok)
33561
33953
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
33562
33954
  const configText = await configResp.text();
33563
- writeFileSync11(configPath, configText);
33955
+ writeFileSync12(configPath, configText);
33564
33956
  }
33565
- if (!existsSync31(onnxPath)) {
33957
+ if (!existsSync32(onnxPath)) {
33566
33958
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
33567
33959
  const onnxResp = await fetch(model.onnxUrl);
33568
33960
  if (!onnxResp.ok)
@@ -33587,7 +33979,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33587
33979
  }
33588
33980
  }
33589
33981
  const fullBuffer = Buffer.concat(chunks);
33590
- writeFileSync11(onnxPath, fullBuffer);
33982
+ writeFileSync12(onnxPath, fullBuffer);
33591
33983
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
33592
33984
  }
33593
33985
  }
@@ -33599,10 +33991,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33599
33991
  throw new Error("ONNX runtime not loaded");
33600
33992
  const onnxPath = modelOnnxPath(this.modelId);
33601
33993
  const configPath = modelConfigPath(this.modelId);
33602
- if (!existsSync31(onnxPath) || !existsSync31(configPath)) {
33994
+ if (!existsSync32(onnxPath) || !existsSync32(configPath)) {
33603
33995
  throw new Error(`Model files not found for ${this.modelId}`);
33604
33996
  }
33605
- this.config = JSON.parse(readFileSync22(configPath, "utf8"));
33997
+ this.config = JSON.parse(readFileSync23(configPath, "utf8"));
33606
33998
  this.session = await this.ort.InferenceSession.create(onnxPath, {
33607
33999
  executionProviders: ["cpu"],
33608
34000
  graphOptimizationLevel: "all"
@@ -34463,13 +34855,13 @@ var init_stream_renderer = __esm({
34463
34855
  });
34464
34856
 
34465
34857
  // packages/cli/dist/tui/edit-history.js
34466
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
34467
- import { join as join42 } from "node:path";
34858
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync13 } from "node:fs";
34859
+ import { join as join43 } from "node:path";
34468
34860
  function createEditHistoryLogger(repoRoot, sessionId) {
34469
- const historyDir = join42(repoRoot, ".oa", "history");
34470
- const logPath = join42(historyDir, "edits.jsonl");
34861
+ const historyDir = join43(repoRoot, ".oa", "history");
34862
+ const logPath = join43(historyDir, "edits.jsonl");
34471
34863
  try {
34472
- mkdirSync12(historyDir, { recursive: true });
34864
+ mkdirSync13(historyDir, { recursive: true });
34473
34865
  } catch {
34474
34866
  }
34475
34867
  function logToolCall(toolName, toolArgs, success) {
@@ -34578,46 +34970,46 @@ var init_edit_history = __esm({
34578
34970
  });
34579
34971
 
34580
34972
  // packages/cli/dist/tui/promptLoader.js
34581
- import { readFileSync as readFileSync23, existsSync as existsSync32 } from "node:fs";
34582
- import { join as join43, dirname as dirname15 } from "node:path";
34973
+ import { readFileSync as readFileSync24, existsSync as existsSync33 } from "node:fs";
34974
+ import { join as join44, dirname as dirname16 } from "node:path";
34583
34975
  import { fileURLToPath as fileURLToPath11 } from "node:url";
34584
34976
  function loadPrompt3(promptPath, vars) {
34585
34977
  let content = cache3.get(promptPath);
34586
34978
  if (content === void 0) {
34587
- const fullPath = join43(PROMPTS_DIR3, promptPath);
34588
- if (!existsSync32(fullPath)) {
34979
+ const fullPath = join44(PROMPTS_DIR3, promptPath);
34980
+ if (!existsSync33(fullPath)) {
34589
34981
  throw new Error(`Prompt file not found: ${fullPath}`);
34590
34982
  }
34591
- content = readFileSync23(fullPath, "utf-8");
34983
+ content = readFileSync24(fullPath, "utf-8");
34592
34984
  cache3.set(promptPath, content);
34593
34985
  }
34594
34986
  if (!vars)
34595
34987
  return content;
34596
34988
  return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
34597
34989
  }
34598
- var __filename3, __dirname5, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
34990
+ var __filename3, __dirname6, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
34599
34991
  var init_promptLoader3 = __esm({
34600
34992
  "packages/cli/dist/tui/promptLoader.js"() {
34601
34993
  "use strict";
34602
34994
  __filename3 = fileURLToPath11(import.meta.url);
34603
- __dirname5 = dirname15(__filename3);
34604
- devPath2 = join43(__dirname5, "..", "..", "prompts");
34605
- publishedPath2 = join43(__dirname5, "..", "prompts");
34606
- PROMPTS_DIR3 = existsSync32(devPath2) ? devPath2 : publishedPath2;
34995
+ __dirname6 = dirname16(__filename3);
34996
+ devPath2 = join44(__dirname6, "..", "..", "prompts");
34997
+ publishedPath2 = join44(__dirname6, "..", "prompts");
34998
+ PROMPTS_DIR3 = existsSync33(devPath2) ? devPath2 : publishedPath2;
34607
34999
  cache3 = /* @__PURE__ */ new Map();
34608
35000
  }
34609
35001
  });
34610
35002
 
34611
35003
  // packages/cli/dist/tui/dream-engine.js
34612
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync33, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
34613
- import { join as join44, basename as basename12 } from "node:path";
35004
+ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
35005
+ import { join as join45, basename as basename12 } from "node:path";
34614
35006
  import { execSync as execSync28 } from "node:child_process";
34615
35007
  function loadAutoresearchMemory(repoRoot) {
34616
- const memoryPath = join44(repoRoot, ".oa", "memory", "autoresearch.json");
34617
- if (!existsSync33(memoryPath))
35008
+ const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
35009
+ if (!existsSync34(memoryPath))
34618
35010
  return "";
34619
35011
  try {
34620
- const raw = readFileSync24(memoryPath, "utf-8");
35012
+ const raw = readFileSync25(memoryPath, "utf-8");
34621
35013
  const data = JSON.parse(raw);
34622
35014
  const sections = [];
34623
35015
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -34807,14 +35199,14 @@ var init_dream_engine = __esm({
34807
35199
  const content = String(args["content"] ?? "");
34808
35200
  if (!rawPath)
34809
35201
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34810
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
35202
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
34811
35203
  if (!targetPath.startsWith(this.autoresearchDir)) {
34812
35204
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34813
35205
  }
34814
35206
  try {
34815
- const dir = join44(targetPath, "..");
34816
- mkdirSync13(dir, { recursive: true });
34817
- writeFileSync12(targetPath, content, "utf-8");
35207
+ const dir = join45(targetPath, "..");
35208
+ mkdirSync14(dir, { recursive: true });
35209
+ writeFileSync13(targetPath, content, "utf-8");
34818
35210
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
34819
35211
  } catch (err) {
34820
35212
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34842,20 +35234,20 @@ var init_dream_engine = __esm({
34842
35234
  const rawPath = String(args["path"] ?? "");
34843
35235
  const oldStr = String(args["old_string"] ?? "");
34844
35236
  const newStr = String(args["new_string"] ?? "");
34845
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
35237
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
34846
35238
  if (!targetPath.startsWith(this.autoresearchDir)) {
34847
35239
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34848
35240
  }
34849
35241
  try {
34850
- if (!existsSync33(targetPath)) {
35242
+ if (!existsSync34(targetPath)) {
34851
35243
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
34852
35244
  }
34853
- let content = readFileSync24(targetPath, "utf-8");
35245
+ let content = readFileSync25(targetPath, "utf-8");
34854
35246
  if (!content.includes(oldStr)) {
34855
35247
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
34856
35248
  }
34857
35249
  content = content.replace(oldStr, newStr);
34858
- writeFileSync12(targetPath, content, "utf-8");
35250
+ writeFileSync13(targetPath, content, "utf-8");
34859
35251
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
34860
35252
  } catch (err) {
34861
35253
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34896,14 +35288,14 @@ var init_dream_engine = __esm({
34896
35288
  const content = String(args["content"] ?? "");
34897
35289
  if (!rawPath)
34898
35290
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34899
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
35291
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
34900
35292
  if (!targetPath.startsWith(this.dreamsDir)) {
34901
35293
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
34902
35294
  }
34903
35295
  try {
34904
- const dir = join44(targetPath, "..");
34905
- mkdirSync13(dir, { recursive: true });
34906
- writeFileSync12(targetPath, content, "utf-8");
35296
+ const dir = join45(targetPath, "..");
35297
+ mkdirSync14(dir, { recursive: true });
35298
+ writeFileSync13(targetPath, content, "utf-8");
34907
35299
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
34908
35300
  } catch (err) {
34909
35301
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34931,20 +35323,20 @@ var init_dream_engine = __esm({
34931
35323
  const rawPath = String(args["path"] ?? "");
34932
35324
  const oldStr = String(args["old_string"] ?? "");
34933
35325
  const newStr = String(args["new_string"] ?? "");
34934
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
35326
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
34935
35327
  if (!targetPath.startsWith(this.dreamsDir)) {
34936
35328
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
34937
35329
  }
34938
35330
  try {
34939
- if (!existsSync33(targetPath)) {
35331
+ if (!existsSync34(targetPath)) {
34940
35332
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
34941
35333
  }
34942
- let content = readFileSync24(targetPath, "utf-8");
35334
+ let content = readFileSync25(targetPath, "utf-8");
34943
35335
  if (!content.includes(oldStr)) {
34944
35336
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
34945
35337
  }
34946
35338
  content = content.replace(oldStr, newStr);
34947
- writeFileSync12(targetPath, content, "utf-8");
35339
+ writeFileSync13(targetPath, content, "utf-8");
34948
35340
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
34949
35341
  } catch (err) {
34950
35342
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34998,7 +35390,7 @@ var init_dream_engine = __esm({
34998
35390
  constructor(config, repoRoot) {
34999
35391
  this.config = config;
35000
35392
  this.repoRoot = repoRoot;
35001
- this.dreamsDir = join44(repoRoot, ".oa", "dreams");
35393
+ this.dreamsDir = join45(repoRoot, ".oa", "dreams");
35002
35394
  this.state = {
35003
35395
  mode: "default",
35004
35396
  active: false,
@@ -35029,7 +35421,7 @@ var init_dream_engine = __esm({
35029
35421
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
35030
35422
  results: []
35031
35423
  };
35032
- mkdirSync13(this.dreamsDir, { recursive: true });
35424
+ mkdirSync14(this.dreamsDir, { recursive: true });
35033
35425
  this.saveDreamState();
35034
35426
  try {
35035
35427
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -35082,8 +35474,8 @@ ${result.summary}`;
35082
35474
  if (mode !== "default" || cycle === totalCycles) {
35083
35475
  renderDreamContraction(cycle);
35084
35476
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
35085
- const summaryPath = join44(this.dreamsDir, `cycle-${cycle}-summary.md`);
35086
- writeFileSync12(summaryPath, cycleSummary, "utf-8");
35477
+ const summaryPath = join45(this.dreamsDir, `cycle-${cycle}-summary.md`);
35478
+ writeFileSync13(summaryPath, cycleSummary, "utf-8");
35087
35479
  }
35088
35480
  if (mode === "lucid" && !this.abortController.signal.aborted) {
35089
35481
  this.saveVersionCheckpoint(cycle);
@@ -35295,7 +35687,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
35295
35687
  }
35296
35688
  /** Build role-specific tool sets for swarm agents */
35297
35689
  buildSwarmTools(role, _workspace) {
35298
- const autoresearchDir = join44(this.repoRoot, ".oa", "autoresearch");
35690
+ const autoresearchDir = join45(this.repoRoot, ".oa", "autoresearch");
35299
35691
  const taskComplete = this.createSwarmTaskCompleteTool(role);
35300
35692
  switch (role) {
35301
35693
  case "researcher": {
@@ -35659,7 +36051,7 @@ INSTRUCTIONS:
35659
36051
  2. Summarize the key learnings and next steps
35660
36052
 
35661
36053
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
35662
- const reportPath = join44(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
36054
+ const reportPath = join45(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
35663
36055
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
35664
36056
 
35665
36057
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -35681,8 +36073,8 @@ ${summaryResult}
35681
36073
  *Generated by open-agents autoresearch swarm*
35682
36074
  `;
35683
36075
  try {
35684
- mkdirSync13(this.dreamsDir, { recursive: true });
35685
- writeFileSync12(reportPath, report, "utf-8");
36076
+ mkdirSync14(this.dreamsDir, { recursive: true });
36077
+ writeFileSync13(reportPath, report, "utf-8");
35686
36078
  } catch {
35687
36079
  }
35688
36080
  renderSwarmComplete(workspace);
@@ -35748,9 +36140,9 @@ ${summaryResult}
35748
36140
  }
35749
36141
  /** Save workspace backup for lucid mode */
35750
36142
  saveVersionCheckpoint(cycle) {
35751
- const checkpointDir = join44(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
36143
+ const checkpointDir = join45(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
35752
36144
  try {
35753
- mkdirSync13(checkpointDir, { recursive: true });
36145
+ mkdirSync14(checkpointDir, { recursive: true });
35754
36146
  try {
35755
36147
  const gitStatus = execSync28("git status --porcelain", {
35756
36148
  cwd: this.repoRoot,
@@ -35767,10 +36159,10 @@ ${summaryResult}
35767
36159
  encoding: "utf-8",
35768
36160
  timeout: 5e3
35769
36161
  }).trim();
35770
- writeFileSync12(join44(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
35771
- writeFileSync12(join44(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
35772
- writeFileSync12(join44(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
35773
- writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({
36162
+ writeFileSync13(join45(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
36163
+ writeFileSync13(join45(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
36164
+ writeFileSync13(join45(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
36165
+ writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({
35774
36166
  cycle,
35775
36167
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
35776
36168
  gitHash,
@@ -35778,7 +36170,7 @@ ${summaryResult}
35778
36170
  }, null, 2), "utf-8");
35779
36171
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
35780
36172
  } catch {
35781
- writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
36173
+ writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
35782
36174
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
35783
36175
  }
35784
36176
  } catch (err) {
@@ -35836,14 +36228,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
35836
36228
  ---
35837
36229
  *Auto-generated by open-agents dream engine*
35838
36230
  `;
35839
- writeFileSync12(join44(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
36231
+ writeFileSync13(join45(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
35840
36232
  } catch {
35841
36233
  }
35842
36234
  }
35843
36235
  /** Save dream state for resume/inspection */
35844
36236
  saveDreamState() {
35845
36237
  try {
35846
- writeFileSync12(join44(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
36238
+ writeFileSync13(join45(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
35847
36239
  } catch {
35848
36240
  }
35849
36241
  }
@@ -36217,8 +36609,8 @@ var init_bless_engine = __esm({
36217
36609
  });
36218
36610
 
36219
36611
  // packages/cli/dist/tui/dmn-engine.js
36220
- import { existsSync as existsSync34, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
36221
- import { join as join45, basename as basename13 } from "node:path";
36612
+ import { existsSync as existsSync35, readFileSync as readFileSync26, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
36613
+ import { join as join46, basename as basename13 } from "node:path";
36222
36614
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
36223
36615
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
36224
36616
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -36331,9 +36723,9 @@ var init_dmn_engine = __esm({
36331
36723
  constructor(config, repoRoot) {
36332
36724
  this.config = config;
36333
36725
  this.repoRoot = repoRoot;
36334
- this.stateDir = join45(repoRoot, ".oa", "dmn");
36335
- this.historyDir = join45(repoRoot, ".oa", "dmn", "cycles");
36336
- mkdirSync14(this.historyDir, { recursive: true });
36726
+ this.stateDir = join46(repoRoot, ".oa", "dmn");
36727
+ this.historyDir = join46(repoRoot, ".oa", "dmn", "cycles");
36728
+ mkdirSync15(this.historyDir, { recursive: true });
36337
36729
  this.loadState();
36338
36730
  }
36339
36731
  get stats() {
@@ -36922,11 +37314,11 @@ OUTPUT: Call task_complete with JSON:
36922
37314
  async gatherMemoryTopics() {
36923
37315
  const topics = [];
36924
37316
  const dirs = [
36925
- join45(this.repoRoot, ".oa", "memory"),
36926
- join45(this.repoRoot, ".open-agents", "memory")
37317
+ join46(this.repoRoot, ".oa", "memory"),
37318
+ join46(this.repoRoot, ".open-agents", "memory")
36927
37319
  ];
36928
37320
  for (const dir of dirs) {
36929
- if (!existsSync34(dir))
37321
+ if (!existsSync35(dir))
36930
37322
  continue;
36931
37323
  try {
36932
37324
  const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
@@ -36942,29 +37334,29 @@ OUTPUT: Call task_complete with JSON:
36942
37334
  }
36943
37335
  // ── State persistence ─────────────────────────────────────────────────
36944
37336
  loadState() {
36945
- const path = join45(this.stateDir, "state.json");
36946
- if (existsSync34(path)) {
37337
+ const path = join46(this.stateDir, "state.json");
37338
+ if (existsSync35(path)) {
36947
37339
  try {
36948
- this.state = JSON.parse(readFileSync25(path, "utf-8"));
37340
+ this.state = JSON.parse(readFileSync26(path, "utf-8"));
36949
37341
  } catch {
36950
37342
  }
36951
37343
  }
36952
37344
  }
36953
37345
  saveState() {
36954
37346
  try {
36955
- writeFileSync13(join45(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
37347
+ writeFileSync14(join46(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
36956
37348
  } catch {
36957
37349
  }
36958
37350
  }
36959
37351
  saveCycleResult(result) {
36960
37352
  try {
36961
37353
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
36962
- writeFileSync13(join45(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
37354
+ writeFileSync14(join46(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
36963
37355
  const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
36964
37356
  if (files.length > 50) {
36965
37357
  for (const old of files.slice(0, files.length - 50)) {
36966
37358
  try {
36967
- unlinkSync5(join45(this.historyDir, old));
37359
+ unlinkSync5(join46(this.historyDir, old));
36968
37360
  } catch {
36969
37361
  }
36970
37362
  }
@@ -36977,8 +37369,8 @@ OUTPUT: Call task_complete with JSON:
36977
37369
  });
36978
37370
 
36979
37371
  // packages/cli/dist/tui/snr-engine.js
36980
- import { existsSync as existsSync35, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
36981
- import { join as join46, basename as basename14 } from "node:path";
37372
+ import { existsSync as existsSync36, readdirSync as readdirSync12, readFileSync as readFileSync27 } from "node:fs";
37373
+ import { join as join47, basename as basename14 } from "node:path";
36982
37374
  function computeDPrime(signalScores, noiseScores) {
36983
37375
  if (signalScores.length === 0 || noiseScores.length === 0)
36984
37376
  return 0;
@@ -37218,11 +37610,11 @@ Call task_complete with the JSON array when done.`, onEvent)
37218
37610
  loadMemoryEntries(topics) {
37219
37611
  const entries = [];
37220
37612
  const dirs = [
37221
- join46(this.repoRoot, ".oa", "memory"),
37222
- join46(this.repoRoot, ".open-agents", "memory")
37613
+ join47(this.repoRoot, ".oa", "memory"),
37614
+ join47(this.repoRoot, ".open-agents", "memory")
37223
37615
  ];
37224
37616
  for (const dir of dirs) {
37225
- if (!existsSync35(dir))
37617
+ if (!existsSync36(dir))
37226
37618
  continue;
37227
37619
  try {
37228
37620
  const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
@@ -37231,7 +37623,7 @@ Call task_complete with the JSON array when done.`, onEvent)
37231
37623
  if (topics.length > 0 && !topics.includes(topic))
37232
37624
  continue;
37233
37625
  try {
37234
- const data = JSON.parse(readFileSync26(join46(dir, f), "utf-8"));
37626
+ const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
37235
37627
  for (const [key, val] of Object.entries(data)) {
37236
37628
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
37237
37629
  entries.push({ topic, key, value });
@@ -37782,8 +38174,8 @@ var init_tool_policy = __esm({
37782
38174
  });
37783
38175
 
37784
38176
  // packages/cli/dist/tui/telegram-bridge.js
37785
- import { mkdirSync as mkdirSync15, existsSync as existsSync36, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
37786
- import { join as join47, resolve as resolve27 } from "node:path";
38177
+ import { mkdirSync as mkdirSync16, existsSync as existsSync37, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
38178
+ import { join as join48, resolve as resolve27 } from "node:path";
37787
38179
  import { writeFile as writeFileAsync } from "node:fs/promises";
37788
38180
  function convertMarkdownToTelegramHTML(md) {
37789
38181
  let html = md;
@@ -38111,7 +38503,7 @@ with summary "no_reply" to silently skip without responding.
38111
38503
  this.polling = true;
38112
38504
  this.abortController = new AbortController();
38113
38505
  try {
38114
- mkdirSync15(this.mediaCacheDir, { recursive: true });
38506
+ mkdirSync16(this.mediaCacheDir, { recursive: true });
38115
38507
  } catch {
38116
38508
  }
38117
38509
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -38548,7 +38940,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
38548
38940
  return null;
38549
38941
  const buffer = Buffer.from(await res.arrayBuffer());
38550
38942
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
38551
- const localPath = join47(this.mediaCacheDir, fileName);
38943
+ const localPath = join48(this.mediaCacheDir, fileName);
38552
38944
  await writeFileAsync(localPath, buffer);
38553
38945
  return localPath;
38554
38946
  } catch {
@@ -40285,11 +40677,11 @@ var init_status_bar = __esm({
40285
40677
  import * as readline2 from "node:readline";
40286
40678
  import { Writable } from "node:stream";
40287
40679
  import { cwd } from "node:process";
40288
- import { resolve as resolve28, join as join48, dirname as dirname16, extname as extname9 } from "node:path";
40680
+ import { resolve as resolve28, join as join49, dirname as dirname17, extname as extname9 } from "node:path";
40289
40681
  import { createRequire as createRequire2 } from "node:module";
40290
40682
  import { fileURLToPath as fileURLToPath12 } from "node:url";
40291
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync14, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync16 } from "node:fs";
40292
- import { existsSync as existsSync37 } from "node:fs";
40683
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync15, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
40684
+ import { existsSync as existsSync38 } from "node:fs";
40293
40685
  import { homedir as homedir13 } from "node:os";
40294
40686
  function formatTimeAgo(date) {
40295
40687
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -40307,14 +40699,14 @@ function formatTimeAgo(date) {
40307
40699
  function getVersion3() {
40308
40700
  try {
40309
40701
  const require2 = createRequire2(import.meta.url);
40310
- const thisDir = dirname16(fileURLToPath12(import.meta.url));
40702
+ const thisDir = dirname17(fileURLToPath12(import.meta.url));
40311
40703
  const candidates = [
40312
- join48(thisDir, "..", "package.json"),
40313
- join48(thisDir, "..", "..", "package.json"),
40314
- join48(thisDir, "..", "..", "..", "package.json")
40704
+ join49(thisDir, "..", "package.json"),
40705
+ join49(thisDir, "..", "..", "package.json"),
40706
+ join49(thisDir, "..", "..", "..", "package.json")
40315
40707
  ];
40316
40708
  for (const pkgPath of candidates) {
40317
- if (existsSync37(pkgPath)) {
40709
+ if (existsSync38(pkgPath)) {
40318
40710
  const pkg = require2(pkgPath);
40319
40711
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
40320
40712
  return pkg.version ?? "0.0.0";
@@ -40520,15 +40912,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
40520
40912
  function gatherMemorySnippets(root) {
40521
40913
  const snippets = [];
40522
40914
  const dirs = [
40523
- join48(root, ".oa", "memory"),
40524
- join48(root, ".open-agents", "memory")
40915
+ join49(root, ".oa", "memory"),
40916
+ join49(root, ".open-agents", "memory")
40525
40917
  ];
40526
40918
  for (const dir of dirs) {
40527
- if (!existsSync37(dir))
40919
+ if (!existsSync38(dir))
40528
40920
  continue;
40529
40921
  try {
40530
40922
  for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
40531
- const data = JSON.parse(readFileSync27(join48(dir, f), "utf-8"));
40923
+ const data = JSON.parse(readFileSync28(join49(dir, f), "utf-8"));
40532
40924
  for (const val of Object.values(data)) {
40533
40925
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
40534
40926
  if (v.length > 10)
@@ -40597,7 +40989,7 @@ function formatDMNToolArgs(toolName, args) {
40597
40989
  return "";
40598
40990
  }
40599
40991
  }
40600
- function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled) {
40992
+ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler) {
40601
40993
  const voiceStyleMap = {
40602
40994
  concise: 1,
40603
40995
  balanced: 3,
@@ -40703,6 +41095,89 @@ ${entry.fullContent}`
40703
41095
  };
40704
41096
  }
40705
41097
  });
41098
+ {
41099
+ const llmCall = async (messages) => {
41100
+ const resp = await backend.chatCompletion({
41101
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
41102
+ tools: [],
41103
+ temperature: 0,
41104
+ maxTokens: 8192,
41105
+ timeoutMs: 12e4
41106
+ });
41107
+ return resp.choices[0]?.message?.content ?? "";
41108
+ };
41109
+ runner.registerTool(new SkillBuildTool(repoRoot, llmCall));
41110
+ }
41111
+ if (slashCommandHandler) {
41112
+ runner.registerTool({
41113
+ name: "slash_command",
41114
+ description: "Invoke a slash command programmatically. Available when /commands auto is set by the user. Safe commands: help, config, models, skills, tools, stats, cost, score, nexus, commands, verbose, stream, brute-force, deep-context, flow, style, emojis, colors, task-type, compact, context, evaluate. Skill commands: /<skill-name> <args>. BLOCKED commands (user-only): quit, exit, destroy, model, endpoint, update, telegram, call, listen, expose, p2p, secrets, dream, bless, clear. Use this to check configuration, run evaluations, discover skills, or adjust modes during a task.",
41115
+ parameters: {
41116
+ type: "object",
41117
+ properties: {
41118
+ command: {
41119
+ type: "string",
41120
+ description: "The slash command to run (without leading /), e.g. 'stats', 'skills security', 'verbose', 'config'"
41121
+ }
41122
+ },
41123
+ required: ["command"]
41124
+ },
41125
+ async execute(args) {
41126
+ const cmd = String(args.command ?? "").trim();
41127
+ if (!cmd) {
41128
+ return { success: false, output: "", error: "Command string is required (e.g. 'stats', 'config', 'skills')" };
41129
+ }
41130
+ const blocked = /* @__PURE__ */ new Set([
41131
+ "quit",
41132
+ "exit",
41133
+ "q",
41134
+ "destroy",
41135
+ "clear",
41136
+ "cls",
41137
+ "model",
41138
+ "endpoint",
41139
+ "ep",
41140
+ "update",
41141
+ "upgrade",
41142
+ "telegram",
41143
+ "tg",
41144
+ "call",
41145
+ "hangup",
41146
+ "listen",
41147
+ "mic",
41148
+ "expose",
41149
+ "p2p",
41150
+ "secrets",
41151
+ "secret",
41152
+ "vault",
41153
+ "dream",
41154
+ "bless",
41155
+ "full-send-bless",
41156
+ "pause",
41157
+ "stop",
41158
+ "resume"
41159
+ ]);
41160
+ const cmdName = cmd.split(/\s+/)[0].toLowerCase();
41161
+ if (blocked.has(cmdName)) {
41162
+ return {
41163
+ success: false,
41164
+ output: "",
41165
+ error: `Command "/${cmdName}" is user-only and cannot be invoked by the agent. Ask the user to run /${cmdName} directly.`
41166
+ };
41167
+ }
41168
+ try {
41169
+ const result = await slashCommandHandler("/" + cmd);
41170
+ return { success: true, output: result || `Command /${cmdName} executed.` };
41171
+ } catch (err) {
41172
+ return {
41173
+ success: false,
41174
+ output: "",
41175
+ error: `Slash command error: ${err instanceof Error ? err.message : String(err)}`
41176
+ };
41177
+ }
41178
+ }
41179
+ });
41180
+ }
40706
41181
  const filesTouched = /* @__PURE__ */ new Set();
40707
41182
  const toolSequence = [];
40708
41183
  const editSessionId = `task-${Date.now()}`;
@@ -41013,6 +41488,7 @@ async function startInteractive(config, repoPath) {
41013
41488
  let currentStyle = PRESET_NAMES.includes(savedSettings.style) ? savedSettings.style : "balanced";
41014
41489
  let deepContextEnabled = savedSettings.deepContext ?? false;
41015
41490
  let flowEnabled = savedSettings.flow === true;
41491
+ let commandsMode = savedSettings.commandsMode ?? "manual";
41016
41492
  if (savedSettings.emojis !== void 0)
41017
41493
  setEmojisEnabled(savedSettings.emojis);
41018
41494
  if (savedSettings.colors !== void 0)
@@ -41192,7 +41668,7 @@ async function startInteractive(config, repoPath) {
41192
41668
  let exposeGateway = null;
41193
41669
  let peerMesh = null;
41194
41670
  let inferenceRouter = null;
41195
- const secretVault = new SecretVault(join48(repoRoot, ".oa", "vault.enc"));
41671
+ const secretVault = new SecretVault(join49(repoRoot, ".oa", "vault.enc"));
41196
41672
  let adminSessionKey = null;
41197
41673
  const callSubAgents = /* @__PURE__ */ new Map();
41198
41674
  const streamRenderer = new StreamRenderer();
@@ -41397,13 +41873,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
41397
41873
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
41398
41874
  return [hits, line];
41399
41875
  }
41400
- const HISTORY_DIR = join48(homedir13(), ".open-agents");
41401
- const HISTORY_FILE = join48(HISTORY_DIR, "repl-history");
41876
+ const HISTORY_DIR = join49(homedir13(), ".open-agents");
41877
+ const HISTORY_FILE = join49(HISTORY_DIR, "repl-history");
41402
41878
  const MAX_HISTORY_LINES = 500;
41403
41879
  let savedHistory = [];
41404
41880
  try {
41405
- if (existsSync37(HISTORY_FILE)) {
41406
- const raw = readFileSync27(HISTORY_FILE, "utf8").trim();
41881
+ if (existsSync38(HISTORY_FILE)) {
41882
+ const raw = readFileSync28(HISTORY_FILE, "utf8").trim();
41407
41883
  if (raw)
41408
41884
  savedHistory = raw.split("\n").reverse();
41409
41885
  }
@@ -41422,12 +41898,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
41422
41898
  if (!line.trim())
41423
41899
  return;
41424
41900
  try {
41425
- mkdirSync16(HISTORY_DIR, { recursive: true });
41901
+ mkdirSync17(HISTORY_DIR, { recursive: true });
41426
41902
  appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
41427
41903
  if (Math.random() < 0.02) {
41428
- const all = readFileSync27(HISTORY_FILE, "utf8").trim().split("\n");
41904
+ const all = readFileSync28(HISTORY_FILE, "utf8").trim().split("\n");
41429
41905
  if (all.length > MAX_HISTORY_LINES) {
41430
- writeFileSync14(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
41906
+ writeFileSync15(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
41431
41907
  }
41432
41908
  }
41433
41909
  } catch {
@@ -41594,6 +42070,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
41594
42070
  flowEnabled = !flowEnabled;
41595
42071
  return flowEnabled;
41596
42072
  },
42073
+ getCommandsMode() {
42074
+ return commandsMode;
42075
+ },
42076
+ setCommandsMode(mode) {
42077
+ commandsMode = mode;
42078
+ },
41597
42079
  setStyle(preset) {
41598
42080
  currentStyle = preset;
41599
42081
  },
@@ -42281,8 +42763,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
42281
42763
  return true;
42282
42764
  },
42283
42765
  destroyProject() {
42284
- const oaPath = join48(repoRoot, OA_DIR);
42285
- if (existsSync37(oaPath)) {
42766
+ const oaPath = join49(repoRoot, OA_DIR);
42767
+ if (existsSync38(oaPath)) {
42286
42768
  try {
42287
42769
  rmSync2(oaPath, { recursive: true, force: true });
42288
42770
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -42444,6 +42926,36 @@ ${sessionCtx}` : "",
42444
42926
  process.stdout.write(`\r\x1B[K${label}`);
42445
42927
  pasteIndicatorShown = true;
42446
42928
  }
42929
+ const buildSlashCommandHandler = () => {
42930
+ if (commandsMode !== "auto")
42931
+ return void 0;
42932
+ return async (command) => {
42933
+ const captured = [];
42934
+ const origWrite = process.stdout.write;
42935
+ process.stdout.write = ((chunk) => {
42936
+ if (typeof chunk === "string") {
42937
+ captured.push(chunk.replace(/\x1B\[[0-9;]*m/g, ""));
42938
+ }
42939
+ return true;
42940
+ });
42941
+ try {
42942
+ const result = await handleSlashCommand(command, commandCtx);
42943
+ process.stdout.write = origWrite;
42944
+ if (result === "exit") {
42945
+ return "Cannot exit via slash_command tool. Ask the user to run /quit directly.";
42946
+ }
42947
+ if (typeof result === "object" && result.type === "skill") {
42948
+ return `Skill "${result.name}" loaded. Content:
42949
+ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" : ""}`;
42950
+ }
42951
+ const output = captured.join("").trim();
42952
+ return output || `Command executed: ${command}`;
42953
+ } catch (err) {
42954
+ process.stdout.write = origWrite;
42955
+ throw err;
42956
+ }
42957
+ };
42958
+ };
42447
42959
  rl.on("line", (line) => {
42448
42960
  persistHistoryLine(line);
42449
42961
  const input = line.trim();
@@ -42568,7 +43080,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
42568
43080
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
42569
43081
  lastCompletedSummary = summary;
42570
43082
  lastTaskMeta = meta ?? null;
42571
- }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled);
43083
+ }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
42572
43084
  activeTask = task;
42573
43085
  showPrompt();
42574
43086
  await task.promise;
@@ -42583,13 +43095,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
42583
43095
  }
42584
43096
  }
42585
43097
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
42586
- const isImage = isImagePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
42587
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
43098
+ const isImage = isImagePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
43099
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
42588
43100
  if (activeTask) {
42589
43101
  if (isImage) {
42590
43102
  try {
42591
43103
  const imgPath = resolve28(repoRoot, cleanPath);
42592
- const imgBuffer = readFileSync27(imgPath);
43104
+ const imgBuffer = readFileSync28(imgPath);
42593
43105
  const base64 = imgBuffer.toString("base64");
42594
43106
  const ext = extname9(cleanPath).toLowerCase();
42595
43107
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -42785,7 +43297,7 @@ NEW TASK: ${fullInput}`;
42785
43297
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
42786
43298
  lastCompletedSummary = summary;
42787
43299
  lastTaskMeta = meta ?? null;
42788
- }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled);
43300
+ }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
42789
43301
  activeTask = task;
42790
43302
  showPrompt();
42791
43303
  await task.promise;
@@ -43103,7 +43615,7 @@ import { glob } from "glob";
43103
43615
  import ignore from "ignore";
43104
43616
  import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
43105
43617
  import { createHash as createHash4 } from "node:crypto";
43106
- import { join as join49, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
43618
+ import { join as join50, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
43107
43619
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
43108
43620
  var init_codebase_indexer = __esm({
43109
43621
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -43147,7 +43659,7 @@ var init_codebase_indexer = __esm({
43147
43659
  const ig = ignore.default();
43148
43660
  if (this.config.respectGitignore) {
43149
43661
  try {
43150
- const gitignoreContent = await readFile16(join49(this.config.rootDir, ".gitignore"), "utf-8");
43662
+ const gitignoreContent = await readFile16(join50(this.config.rootDir, ".gitignore"), "utf-8");
43151
43663
  ig.add(gitignoreContent);
43152
43664
  } catch {
43153
43665
  }
@@ -43162,7 +43674,7 @@ var init_codebase_indexer = __esm({
43162
43674
  for (const relativePath of files) {
43163
43675
  if (ig.ignores(relativePath))
43164
43676
  continue;
43165
- const fullPath = join49(this.config.rootDir, relativePath);
43677
+ const fullPath = join50(this.config.rootDir, relativePath);
43166
43678
  try {
43167
43679
  const fileStat = await stat4(fullPath);
43168
43680
  if (fileStat.size > this.config.maxFileSize)
@@ -43208,7 +43720,7 @@ var init_codebase_indexer = __esm({
43208
43720
  if (!child) {
43209
43721
  child = {
43210
43722
  name: part,
43211
- path: join49(current.path, part),
43723
+ path: join50(current.path, part),
43212
43724
  type: "directory",
43213
43725
  children: []
43214
43726
  };
@@ -43291,13 +43803,13 @@ __export(index_repo_exports, {
43291
43803
  indexRepoCommand: () => indexRepoCommand
43292
43804
  });
43293
43805
  import { resolve as resolve29 } from "node:path";
43294
- import { existsSync as existsSync38, statSync as statSync11 } from "node:fs";
43806
+ import { existsSync as existsSync39, statSync as statSync11 } from "node:fs";
43295
43807
  import { cwd as cwd2 } from "node:process";
43296
43808
  async function indexRepoCommand(opts, _config) {
43297
43809
  const repoRoot = resolve29(opts.repoPath ?? cwd2());
43298
43810
  printHeader("Index Repository");
43299
43811
  printInfo(`Indexing: ${repoRoot}`);
43300
- if (!existsSync38(repoRoot)) {
43812
+ if (!existsSync39(repoRoot)) {
43301
43813
  printError(`Path does not exist: ${repoRoot}`);
43302
43814
  process.exit(1);
43303
43815
  }
@@ -43549,7 +44061,7 @@ var config_exports = {};
43549
44061
  __export(config_exports, {
43550
44062
  configCommand: () => configCommand
43551
44063
  });
43552
- import { join as join50, resolve as resolve30 } from "node:path";
44064
+ import { join as join51, resolve as resolve30 } from "node:path";
43553
44065
  import { homedir as homedir14 } from "node:os";
43554
44066
  import { cwd as cwd3 } from "node:process";
43555
44067
  function redactIfSensitive(key, value) {
@@ -43608,7 +44120,7 @@ function handleShow(opts, config) {
43608
44120
  }
43609
44121
  }
43610
44122
  printSection("Config File");
43611
- printInfo(`~/.open-agents/config.json (${join50(homedir14(), ".open-agents", "config.json")})`);
44123
+ printInfo(`~/.open-agents/config.json (${join51(homedir14(), ".open-agents", "config.json")})`);
43612
44124
  printSection("Priority Chain");
43613
44125
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
43614
44126
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -43647,7 +44159,7 @@ function handleSet(opts, _config) {
43647
44159
  const coerced = coerceForSettings(key, value);
43648
44160
  saveProjectSettings(repoRoot, { [key]: coerced });
43649
44161
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
43650
- printInfo(`Saved to ${join50(repoRoot, ".oa", "settings.json")}`);
44162
+ printInfo(`Saved to ${join51(repoRoot, ".oa", "settings.json")}`);
43651
44163
  printInfo("This override applies only when running in this workspace.");
43652
44164
  } catch (err) {
43653
44165
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -43866,8 +44378,8 @@ __export(eval_exports, {
43866
44378
  evalCommand: () => evalCommand
43867
44379
  });
43868
44380
  import { tmpdir as tmpdir7 } from "node:os";
43869
- import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "node:fs";
43870
- import { join as join51 } from "node:path";
44381
+ import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "node:fs";
44382
+ import { join as join52 } from "node:path";
43871
44383
  async function evalCommand(opts, config) {
43872
44384
  const suiteName = opts.suite ?? "basic";
43873
44385
  const suite = SUITES[suiteName];
@@ -43992,9 +44504,9 @@ async function evalCommand(opts, config) {
43992
44504
  process.exit(failed > 0 ? 1 : 0);
43993
44505
  }
43994
44506
  function createTempEvalRepo() {
43995
- const dir = join51(tmpdir7(), `open-agents-eval-${Date.now()}`);
43996
- mkdirSync17(dir, { recursive: true });
43997
- writeFileSync15(join51(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
44507
+ const dir = join52(tmpdir7(), `open-agents-eval-${Date.now()}`);
44508
+ mkdirSync18(dir, { recursive: true });
44509
+ writeFileSync16(join52(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
43998
44510
  return dir;
43999
44511
  }
44000
44512
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -44054,7 +44566,7 @@ init_updater();
44054
44566
  import { parseArgs as nodeParseArgs2 } from "node:util";
44055
44567
  import { createRequire as createRequire3 } from "node:module";
44056
44568
  import { fileURLToPath as fileURLToPath13 } from "node:url";
44057
- import { dirname as dirname17, join as join52 } from "node:path";
44569
+ import { dirname as dirname18, join as join53 } from "node:path";
44058
44570
 
44059
44571
  // packages/cli/dist/cli.js
44060
44572
  import { createInterface } from "node:readline";
@@ -44161,7 +44673,7 @@ init_output();
44161
44673
  function getVersion4() {
44162
44674
  try {
44163
44675
  const require2 = createRequire3(import.meta.url);
44164
- const pkgPath = join52(dirname17(fileURLToPath13(import.meta.url)), "..", "package.json");
44676
+ const pkgPath = join53(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
44165
44677
  const pkg = require2(pkgPath);
44166
44678
  return pkg.version;
44167
44679
  } catch {