open-agents-ai 0.99.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: "",
@@ -16892,6 +17161,14 @@ ${this.options.dynamicContext}`,
16892
17161
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
16893
17162
  });
16894
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
+ }
16895
17172
  /**
16896
17173
  * If paused, block until resume() or abort() is called.
16897
17174
  * Returns true if the loop should continue, false if aborted while paused.
@@ -17343,7 +17620,7 @@ You have used ${totalTurns} turns and ${toolCallCount} tool calls so far. The ta
17343
17620
 
17344
17621
  You have ${this.options.maxTurns} more turns. Continue making progress. Call task_complete when the task is fully done.`
17345
17622
  });
17346
- const compacted = await this.compactMessages(messages);
17623
+ const compacted = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
17347
17624
  if (compacted !== messages) {
17348
17625
  messages.length = 0;
17349
17626
  messages.push(...compacted);
@@ -17407,7 +17684,7 @@ Integrate this guidance into your current approach. Continue working on the task
17407
17684
  this._pendingCompaction = null;
17408
17685
  compactedMsgs = await this.compactMessages(messages, strategy, true);
17409
17686
  } else {
17410
- compactedMsgs = await this.compactMessages(messages);
17687
+ compactedMsgs = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
17411
17688
  }
17412
17689
  const chatRequest = { messages: compactedMsgs, tools: toolDefs, temperature: this.options.temperature, maxTokens: this.options.maxTokens, timeoutMs: this.options.requestTimeoutMs };
17413
17690
  let response;
@@ -17685,10 +17962,10 @@ ${marker}` : marker);
17685
17962
  if (!this._workingDirectory)
17686
17963
  return;
17687
17964
  try {
17688
- const { mkdirSync: mkdirSync18, writeFileSync: writeFileSync16 } = __require("node:fs");
17689
- const { join: join53 } = __require("node:path");
17690
- const sessionDir = join53(this._workingDirectory, ".oa", "session", this._sessionId);
17691
- 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 });
17692
17969
  const checkpoint = {
17693
17970
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
17694
17971
  sessionId: this._sessionId,
@@ -17700,7 +17977,7 @@ ${marker}` : marker);
17700
17977
  memexEntryCount: this._memexArchive.size,
17701
17978
  fileRegistrySize: this._fileRegistry.size
17702
17979
  };
17703
- writeFileSync16(join53(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17980
+ writeFileSync17(join54(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17704
17981
  } catch {
17705
17982
  }
17706
17983
  }
@@ -17992,6 +18269,7 @@ ${newerSummary}` : newerSummary;
17992
18269
  const commandResults = [];
17993
18270
  const searchFindings = [];
17994
18271
  const errors = [];
18272
+ let skillResults;
17995
18273
  let toolCallCount = 0;
17996
18274
  for (const msg of messages) {
17997
18275
  if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.trim()) {
@@ -18085,6 +18363,19 @@ ${newerSummary}` : newerSummary;
18085
18363
  searchFindings.push(`find "${pattern}": ${files.length} files \u2014 ${files.slice(0, 5).join(", ")}`);
18086
18364
  break;
18087
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
+ }
18088
18379
  default: {
18089
18380
  if (content.startsWith("Error:"))
18090
18381
  errors.push(`${tc.name}: ${content.slice(0, 200)}`);
@@ -18133,6 +18424,13 @@ ${newerSummary}` : newerSummary;
18133
18424
  }
18134
18425
  parts.push("");
18135
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
+ }
18136
18434
  if (errors.length > 0) {
18137
18435
  parts.push("### Errors Encountered");
18138
18436
  for (const error of errors.slice(0, 5)) {
@@ -18310,11 +18608,24 @@ ${newerSummary}` : newerSummary;
18310
18608
  context: action,
18311
18609
  error: content.slice(0, 300)
18312
18610
  });
18611
+ } else if (tc.name === "skill_build" || tc.name === "skill_execute" || tc.name === "memory_read") {
18612
+ successes.push(`${action}: ${content.slice(0, 200)}`);
18313
18613
  } else {
18314
18614
  successes.push(`${action} \u2192 ok`);
18315
18615
  }
18316
18616
  }
18317
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
+ }
18318
18629
  const parts = [];
18319
18630
  parts.push(`## Error-Focused Compact
18320
18631
  `);
@@ -18328,6 +18639,12 @@ ${newerSummary}` : newerSummary;
18328
18639
  }
18329
18640
  parts.push("");
18330
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
+ }
18331
18648
  if (successes.length > 0) {
18332
18649
  parts.push(`### Successful Operations (${successes.length} total)`);
18333
18650
  for (const s of successes.slice(0, 10))
@@ -19478,8 +19795,8 @@ __export(listen_exports, {
19478
19795
  waitForTranscribeCli: () => waitForTranscribeCli
19479
19796
  });
19480
19797
  import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
19481
- import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
19482
- 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";
19483
19800
  import { homedir as homedir8 } from "node:os";
19484
19801
  import { fileURLToPath as fileURLToPath8 } from "node:url";
19485
19802
  import { EventEmitter } from "node:events";
@@ -19563,17 +19880,17 @@ function findMicCaptureCommand() {
19563
19880
  return null;
19564
19881
  }
19565
19882
  function findLiveWhisperScript() {
19566
- const thisDir = dirname11(fileURLToPath8(import.meta.url));
19883
+ const thisDir = dirname12(fileURLToPath8(import.meta.url));
19567
19884
  const candidates = [
19568
- join33(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
19569
- join33(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
19570
- 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"),
19571
19888
  // npm install layout — scripts bundled alongside dist
19572
- join33(thisDir, "../scripts/live-whisper.py"),
19573
- join33(thisDir, "../../scripts/live-whisper.py")
19889
+ join34(thisDir, "../scripts/live-whisper.py"),
19890
+ join34(thisDir, "../../scripts/live-whisper.py")
19574
19891
  ];
19575
19892
  for (const p of candidates) {
19576
- if (existsSync24(p))
19893
+ if (existsSync25(p))
19577
19894
  return p;
19578
19895
  }
19579
19896
  try {
@@ -19583,21 +19900,21 @@ function findLiveWhisperScript() {
19583
19900
  stdio: ["pipe", "pipe", "pipe"]
19584
19901
  }).trim();
19585
19902
  const candidates2 = [
19586
- join33(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
19587
- 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")
19588
19905
  ];
19589
19906
  for (const p of candidates2) {
19590
- if (existsSync24(p))
19907
+ if (existsSync25(p))
19591
19908
  return p;
19592
19909
  }
19593
19910
  } catch {
19594
19911
  }
19595
- const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19596
- if (existsSync24(nvmBase)) {
19912
+ const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
19913
+ if (existsSync25(nvmBase)) {
19597
19914
  try {
19598
19915
  for (const ver of readdirSync6(nvmBase)) {
19599
- const p = join33(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19600
- if (existsSync24(p))
19916
+ const p = join34(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19917
+ if (existsSync25(p))
19601
19918
  return p;
19602
19919
  }
19603
19920
  } catch {
@@ -19615,7 +19932,7 @@ function ensureTranscribeCliBackground() {
19615
19932
  timeout: 5e3,
19616
19933
  stdio: ["pipe", "pipe", "pipe"]
19617
19934
  }).trim();
19618
- if (existsSync24(join33(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19935
+ if (existsSync25(join34(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19619
19936
  return true;
19620
19937
  }
19621
19938
  } catch {
@@ -19838,24 +20155,24 @@ var init_listen = __esm({
19838
20155
  timeout: 5e3,
19839
20156
  stdio: ["pipe", "pipe", "pipe"]
19840
20157
  }).trim();
19841
- const tcPath = join33(globalRoot, "transcribe-cli");
19842
- if (existsSync24(join33(tcPath, "dist", "index.js"))) {
20158
+ const tcPath = join34(globalRoot, "transcribe-cli");
20159
+ if (existsSync25(join34(tcPath, "dist", "index.js"))) {
19843
20160
  const { createRequire: createRequire4 } = await import("node:module");
19844
20161
  const req = createRequire4(import.meta.url);
19845
- return req(join33(tcPath, "dist", "index.js"));
20162
+ return req(join34(tcPath, "dist", "index.js"));
19846
20163
  }
19847
20164
  } catch {
19848
20165
  }
19849
- const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19850
- if (existsSync24(nvmBase)) {
20166
+ const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
20167
+ if (existsSync25(nvmBase)) {
19851
20168
  try {
19852
20169
  const { readdirSync: readdirSync15 } = await import("node:fs");
19853
20170
  for (const ver of readdirSync15(nvmBase)) {
19854
- const tcPath = join33(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
19855
- 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"))) {
19856
20173
  const { createRequire: createRequire4 } = await import("node:module");
19857
20174
  const req = createRequire4(import.meta.url);
19858
- return req(join33(tcPath, "dist", "index.js"));
20175
+ return req(join34(tcPath, "dist", "index.js"));
19859
20176
  }
19860
20177
  }
19861
20178
  } catch {
@@ -20137,10 +20454,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
20137
20454
  });
20138
20455
  if (outputDir) {
20139
20456
  const { basename: basename16 } = await import("node:path");
20140
- const transcriptDir = join33(outputDir, ".oa", "transcripts");
20141
- mkdirSync6(transcriptDir, { recursive: true });
20142
- const outFile = join33(transcriptDir, `${basename16(filePath)}.txt`);
20143
- 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");
20144
20461
  }
20145
20462
  return {
20146
20463
  text: result.text,
@@ -25740,8 +26057,8 @@ var init_types = __esm({
25740
26057
 
25741
26058
  // packages/cli/dist/tui/p2p/secret-vault.js
25742
26059
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
25743
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync25, mkdirSync as mkdirSync7 } from "node:fs";
25744
- 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";
25745
26062
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
25746
26063
  var init_secret_vault = __esm({
25747
26064
  "packages/cli/dist/tui/p2p/secret-vault.js"() {
@@ -25952,19 +26269,19 @@ var init_secret_vault = __esm({
25952
26269
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
25953
26270
  const tag = cipher.getAuthTag();
25954
26271
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
25955
- const dir = dirname12(this.storePath);
25956
- if (!existsSync25(dir))
25957
- mkdirSync7(dir, { recursive: true });
25958
- 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 });
25959
26276
  }
25960
26277
  /**
25961
26278
  * Load vault from disk, decrypting with the given passphrase.
25962
26279
  * Returns the number of secrets loaded.
25963
26280
  */
25964
26281
  load(passphrase) {
25965
- if (!this.storePath || !existsSync25(this.storePath))
26282
+ if (!this.storePath || !existsSync26(this.storePath))
25966
26283
  return 0;
25967
- const blob = readFileSync17(this.storePath);
26284
+ const blob = readFileSync18(this.storePath);
25968
26285
  if (blob.length < SALT_LEN + IV_LEN + 16) {
25969
26286
  throw new Error("Vault file is corrupted (too small)");
25970
26287
  }
@@ -27184,32 +27501,32 @@ var init_render2 = __esm({
27184
27501
  });
27185
27502
 
27186
27503
  // packages/prompts/dist/promptLoader.js
27187
- import { readFileSync as readFileSync18, existsSync as existsSync26 } from "node:fs";
27188
- 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";
27189
27506
  import { fileURLToPath as fileURLToPath9 } from "node:url";
27190
27507
  function loadPrompt2(promptPath, vars) {
27191
27508
  let content = cache2.get(promptPath);
27192
27509
  if (content === void 0) {
27193
- const fullPath = join35(PROMPTS_DIR2, promptPath);
27194
- if (!existsSync26(fullPath)) {
27510
+ const fullPath = join36(PROMPTS_DIR2, promptPath);
27511
+ if (!existsSync27(fullPath)) {
27195
27512
  throw new Error(`Prompt file not found: ${fullPath}`);
27196
27513
  }
27197
- content = readFileSync18(fullPath, "utf-8");
27514
+ content = readFileSync19(fullPath, "utf-8");
27198
27515
  cache2.set(promptPath, content);
27199
27516
  }
27200
27517
  if (!vars)
27201
27518
  return content;
27202
27519
  return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
27203
27520
  }
27204
- var __filename2, __dirname4, devPath, publishedPath, PROMPTS_DIR2, cache2;
27521
+ var __filename2, __dirname5, devPath, publishedPath, PROMPTS_DIR2, cache2;
27205
27522
  var init_promptLoader2 = __esm({
27206
27523
  "packages/prompts/dist/promptLoader.js"() {
27207
27524
  "use strict";
27208
27525
  __filename2 = fileURLToPath9(import.meta.url);
27209
- __dirname4 = dirname13(__filename2);
27210
- devPath = join35(__dirname4, "..", "templates");
27211
- publishedPath = join35(__dirname4, "..", "prompts", "templates");
27212
- 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;
27213
27530
  cache2 = /* @__PURE__ */ new Map();
27214
27531
  }
27215
27532
  });
@@ -27320,7 +27637,7 @@ var init_task_templates = __esm({
27320
27637
  });
27321
27638
 
27322
27639
  // packages/prompts/dist/index.js
27323
- import { join as join36, dirname as dirname14 } from "node:path";
27640
+ import { join as join37, dirname as dirname15 } from "node:path";
27324
27641
  import { fileURLToPath as fileURLToPath10 } from "node:url";
27325
27642
  var _dir, _packageRoot;
27326
27643
  var init_dist6 = __esm({
@@ -27330,27 +27647,27 @@ var init_dist6 = __esm({
27330
27647
  init_render2();
27331
27648
  init_task_templates();
27332
27649
  init_render2();
27333
- _dir = dirname14(fileURLToPath10(import.meta.url));
27334
- _packageRoot = join36(_dir, "..");
27650
+ _dir = dirname15(fileURLToPath10(import.meta.url));
27651
+ _packageRoot = join37(_dir, "..");
27335
27652
  }
27336
27653
  });
27337
27654
 
27338
27655
  // packages/cli/dist/tui/oa-directory.js
27339
- 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";
27340
- 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";
27341
27658
  import { homedir as homedir9 } from "node:os";
27342
27659
  function initOaDirectory(repoRoot) {
27343
- const oaPath = join37(repoRoot, OA_DIR);
27660
+ const oaPath = join38(repoRoot, OA_DIR);
27344
27661
  for (const sub of SUBDIRS) {
27345
- mkdirSync8(join37(oaPath, sub), { recursive: true });
27662
+ mkdirSync9(join38(oaPath, sub), { recursive: true });
27346
27663
  }
27347
27664
  try {
27348
- const gitignorePath = join37(repoRoot, ".gitignore");
27665
+ const gitignorePath = join38(repoRoot, ".gitignore");
27349
27666
  const settingsPattern = ".oa/settings.json";
27350
- if (existsSync27(gitignorePath)) {
27351
- const content = readFileSync19(gitignorePath, "utf-8");
27667
+ if (existsSync28(gitignorePath)) {
27668
+ const content = readFileSync20(gitignorePath, "utf-8");
27352
27669
  if (!content.includes(settingsPattern)) {
27353
- writeFileSync8(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
27670
+ writeFileSync9(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
27354
27671
  }
27355
27672
  }
27356
27673
  } catch {
@@ -27358,41 +27675,41 @@ function initOaDirectory(repoRoot) {
27358
27675
  return oaPath;
27359
27676
  }
27360
27677
  function hasOaDirectory(repoRoot) {
27361
- return existsSync27(join37(repoRoot, OA_DIR, "index"));
27678
+ return existsSync28(join38(repoRoot, OA_DIR, "index"));
27362
27679
  }
27363
27680
  function loadProjectSettings(repoRoot) {
27364
- const settingsPath = join37(repoRoot, OA_DIR, "settings.json");
27681
+ const settingsPath = join38(repoRoot, OA_DIR, "settings.json");
27365
27682
  try {
27366
- if (existsSync27(settingsPath)) {
27367
- return JSON.parse(readFileSync19(settingsPath, "utf-8"));
27683
+ if (existsSync28(settingsPath)) {
27684
+ return JSON.parse(readFileSync20(settingsPath, "utf-8"));
27368
27685
  }
27369
27686
  } catch {
27370
27687
  }
27371
27688
  return {};
27372
27689
  }
27373
27690
  function saveProjectSettings(repoRoot, settings) {
27374
- const oaPath = join37(repoRoot, OA_DIR);
27375
- mkdirSync8(oaPath, { recursive: true });
27691
+ const oaPath = join38(repoRoot, OA_DIR);
27692
+ mkdirSync9(oaPath, { recursive: true });
27376
27693
  const existing = loadProjectSettings(repoRoot);
27377
27694
  const merged = { ...existing, ...settings };
27378
- 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 });
27379
27696
  }
27380
27697
  function loadGlobalSettings() {
27381
- const settingsPath = join37(homedir9(), ".open-agents", "settings.json");
27698
+ const settingsPath = join38(homedir9(), ".open-agents", "settings.json");
27382
27699
  try {
27383
- if (existsSync27(settingsPath)) {
27384
- return JSON.parse(readFileSync19(settingsPath, "utf-8"));
27700
+ if (existsSync28(settingsPath)) {
27701
+ return JSON.parse(readFileSync20(settingsPath, "utf-8"));
27385
27702
  }
27386
27703
  } catch {
27387
27704
  }
27388
27705
  return {};
27389
27706
  }
27390
27707
  function saveGlobalSettings(settings) {
27391
- const dir = join37(homedir9(), ".open-agents");
27392
- mkdirSync8(dir, { recursive: true });
27708
+ const dir = join38(homedir9(), ".open-agents");
27709
+ mkdirSync9(dir, { recursive: true });
27393
27710
  const existing = loadGlobalSettings();
27394
27711
  const merged = { ...existing, ...settings };
27395
- 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 });
27396
27713
  }
27397
27714
  function resolveSettings(repoRoot) {
27398
27715
  const global = loadGlobalSettings();
@@ -27407,12 +27724,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27407
27724
  while (dir && !visited.has(dir)) {
27408
27725
  visited.add(dir);
27409
27726
  for (const name of CONTEXT_FILES) {
27410
- const filePath = join37(dir, name);
27727
+ const filePath = join38(dir, name);
27411
27728
  const normalizedName = name.toLowerCase();
27412
- if (existsSync27(filePath) && !seen.has(filePath)) {
27729
+ if (existsSync28(filePath) && !seen.has(filePath)) {
27413
27730
  seen.add(filePath);
27414
27731
  try {
27415
- let content = readFileSync19(filePath, "utf-8");
27732
+ let content = readFileSync20(filePath, "utf-8");
27416
27733
  if (content.length > maxContentLen) {
27417
27734
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
27418
27735
  }
@@ -27426,11 +27743,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27426
27743
  }
27427
27744
  }
27428
27745
  }
27429
- const projectMap = join37(dir, OA_DIR, "context", "project-map.md");
27430
- if (existsSync27(projectMap) && !seen.has(projectMap)) {
27746
+ const projectMap = join38(dir, OA_DIR, "context", "project-map.md");
27747
+ if (existsSync28(projectMap) && !seen.has(projectMap)) {
27431
27748
  seen.add(projectMap);
27432
27749
  try {
27433
- let content = readFileSync19(projectMap, "utf-8");
27750
+ let content = readFileSync20(projectMap, "utf-8");
27434
27751
  if (content.length > maxContentLen) {
27435
27752
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
27436
27753
  }
@@ -27442,7 +27759,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27442
27759
  } catch {
27443
27760
  }
27444
27761
  }
27445
- const parent = join37(dir, "..");
27762
+ const parent = join38(dir, "..");
27446
27763
  if (parent === dir)
27447
27764
  break;
27448
27765
  dir = parent;
@@ -27460,9 +27777,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
27460
27777
  return found;
27461
27778
  }
27462
27779
  function readIndexMeta(repoRoot) {
27463
- const metaPath = join37(repoRoot, OA_DIR, "index", "meta.json");
27780
+ const metaPath = join38(repoRoot, OA_DIR, "index", "meta.json");
27464
27781
  try {
27465
- return JSON.parse(readFileSync19(metaPath, "utf-8"));
27782
+ return JSON.parse(readFileSync20(metaPath, "utf-8"));
27466
27783
  } catch {
27467
27784
  return null;
27468
27785
  }
@@ -27513,28 +27830,28 @@ ${tree}\`\`\`
27513
27830
  sections.push("");
27514
27831
  }
27515
27832
  const content = sections.join("\n");
27516
- const contextDir = join37(repoRoot, OA_DIR, "context");
27517
- mkdirSync8(contextDir, { recursive: true });
27518
- 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");
27519
27836
  return content;
27520
27837
  }
27521
27838
  function saveSession(repoRoot, session) {
27522
- const historyDir = join37(repoRoot, OA_DIR, "history");
27523
- mkdirSync8(historyDir, { recursive: true });
27524
- 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");
27525
27842
  }
27526
27843
  function loadRecentSessions(repoRoot, limit = 5) {
27527
- const historyDir = join37(repoRoot, OA_DIR, "history");
27528
- if (!existsSync27(historyDir))
27844
+ const historyDir = join38(repoRoot, OA_DIR, "history");
27845
+ if (!existsSync28(historyDir))
27529
27846
  return [];
27530
27847
  try {
27531
27848
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
27532
- const stat5 = statSync9(join37(historyDir, f));
27849
+ const stat5 = statSync9(join38(historyDir, f));
27533
27850
  return { file: f, mtime: stat5.mtimeMs };
27534
27851
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
27535
27852
  return files.map((f) => {
27536
27853
  try {
27537
- return JSON.parse(readFileSync19(join37(historyDir, f.file), "utf-8"));
27854
+ return JSON.parse(readFileSync20(join38(historyDir, f.file), "utf-8"));
27538
27855
  } catch {
27539
27856
  return null;
27540
27857
  }
@@ -27544,16 +27861,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
27544
27861
  }
27545
27862
  }
27546
27863
  function savePendingTask(repoRoot, task) {
27547
- const historyDir = join37(repoRoot, OA_DIR, "history");
27548
- mkdirSync8(historyDir, { recursive: true });
27549
- 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");
27550
27867
  }
27551
27868
  function loadPendingTask(repoRoot) {
27552
- const filePath = join37(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27869
+ const filePath = join38(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27553
27870
  try {
27554
- if (!existsSync27(filePath))
27871
+ if (!existsSync28(filePath))
27555
27872
  return null;
27556
- const data = JSON.parse(readFileSync19(filePath, "utf-8"));
27873
+ const data = JSON.parse(readFileSync20(filePath, "utf-8"));
27557
27874
  try {
27558
27875
  unlinkSync3(filePath);
27559
27876
  } catch {
@@ -27564,13 +27881,13 @@ function loadPendingTask(repoRoot) {
27564
27881
  }
27565
27882
  }
27566
27883
  function saveSessionContext(repoRoot, entry) {
27567
- const contextDir = join37(repoRoot, OA_DIR, "context");
27568
- mkdirSync8(contextDir, { recursive: true });
27569
- 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);
27570
27887
  let ctx;
27571
27888
  try {
27572
- if (existsSync27(filePath)) {
27573
- ctx = JSON.parse(readFileSync19(filePath, "utf-8"));
27889
+ if (existsSync28(filePath)) {
27890
+ ctx = JSON.parse(readFileSync20(filePath, "utf-8"));
27574
27891
  } else {
27575
27892
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
27576
27893
  }
@@ -27582,14 +27899,14 @@ function saveSessionContext(repoRoot, entry) {
27582
27899
  ctx.entries = ctx.entries.slice(-ctx.maxEntries);
27583
27900
  }
27584
27901
  ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
27585
- writeFileSync8(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
27902
+ writeFileSync9(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
27586
27903
  }
27587
27904
  function loadSessionContext(repoRoot) {
27588
- const filePath = join37(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27905
+ const filePath = join38(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27589
27906
  try {
27590
- if (!existsSync27(filePath))
27907
+ if (!existsSync28(filePath))
27591
27908
  return null;
27592
- return JSON.parse(readFileSync19(filePath, "utf-8"));
27909
+ return JSON.parse(readFileSync20(filePath, "utf-8"));
27593
27910
  } catch {
27594
27911
  return null;
27595
27912
  }
@@ -27636,12 +27953,12 @@ function detectManifests(repoRoot) {
27636
27953
  { file: "docker-compose.yaml", type: "Docker Compose" }
27637
27954
  ];
27638
27955
  for (const check of checks) {
27639
- const filePath = join37(repoRoot, check.file);
27640
- if (existsSync27(filePath)) {
27956
+ const filePath = join38(repoRoot, check.file);
27957
+ if (existsSync28(filePath)) {
27641
27958
  let name;
27642
27959
  if (check.nameField) {
27643
27960
  try {
27644
- const data = JSON.parse(readFileSync19(filePath, "utf-8"));
27961
+ const data = JSON.parse(readFileSync20(filePath, "utf-8"));
27645
27962
  name = data[check.nameField];
27646
27963
  } catch {
27647
27964
  }
@@ -27670,7 +27987,7 @@ function findKeyFiles(repoRoot) {
27670
27987
  { pattern: "CLAUDE.md", description: "Claude Code context" }
27671
27988
  ];
27672
27989
  for (const check of checks) {
27673
- if (existsSync27(join37(repoRoot, check.pattern))) {
27990
+ if (existsSync28(join38(repoRoot, check.pattern))) {
27674
27991
  keyFiles.push({ path: check.pattern, description: check.description });
27675
27992
  }
27676
27993
  }
@@ -27696,12 +28013,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
27696
28013
  if (entry.isDirectory()) {
27697
28014
  let fileCount = 0;
27698
28015
  try {
27699
- fileCount = readdirSync7(join37(root, entry.name)).filter((f) => !f.startsWith(".")).length;
28016
+ fileCount = readdirSync7(join38(root, entry.name)).filter((f) => !f.startsWith(".")).length;
27700
28017
  } catch {
27701
28018
  }
27702
28019
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
27703
28020
  `;
27704
- result += buildDirTree(join37(root, entry.name), maxDepth, childPrefix, depth + 1);
28021
+ result += buildDirTree(join38(root, entry.name), maxDepth, childPrefix, depth + 1);
27705
28022
  } else if (depth < maxDepth) {
27706
28023
  result += `${prefix}${connector}${entry.name}
27707
28024
  `;
@@ -27755,8 +28072,8 @@ var init_oa_directory = __esm({
27755
28072
  // packages/cli/dist/tui/setup.js
27756
28073
  import * as readline from "node:readline";
27757
28074
  import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
27758
- import { existsSync as existsSync28, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
27759
- 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";
27760
28077
  import { homedir as homedir10, platform } from "node:os";
27761
28078
  function detectSystemSpecs() {
27762
28079
  let totalRamGB = 0;
@@ -27989,7 +28306,7 @@ async function installOllamaMac(_rl) {
27989
28306
  execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
27990
28307
  if (!hasCmd("brew")) {
27991
28308
  try {
27992
- const brewPrefix = existsSync28("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
28309
+ const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
27993
28310
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
27994
28311
  } catch {
27995
28312
  }
@@ -28743,10 +29060,10 @@ async function doSetup(config, rl) {
28743
29060
  `PARAMETER num_predict ${numPredict}`,
28744
29061
  `PARAMETER stop "<|endoftext|>"`
28745
29062
  ].join("\n");
28746
- const modelDir2 = join38(homedir10(), ".open-agents", "models");
28747
- mkdirSync9(modelDir2, { recursive: true });
28748
- const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
28749
- 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");
28750
29067
  process.stdout.write(` ${c2.dim("Creating model...")} `);
28751
29068
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
28752
29069
  stdio: "pipe",
@@ -28791,7 +29108,7 @@ async function isModelAvailable(config) {
28791
29108
  }
28792
29109
  function isFirstRun() {
28793
29110
  try {
28794
- return !existsSync28(join38(homedir10(), ".open-agents", "config.json"));
29111
+ return !existsSync29(join39(homedir10(), ".open-agents", "config.json"));
28795
29112
  } catch {
28796
29113
  return true;
28797
29114
  }
@@ -28828,7 +29145,7 @@ function detectPkgManager() {
28828
29145
  return null;
28829
29146
  }
28830
29147
  function getVenvDir() {
28831
- return join38(homedir10(), ".open-agents", "venv");
29148
+ return join39(homedir10(), ".open-agents", "venv");
28832
29149
  }
28833
29150
  function hasVenvModule() {
28834
29151
  try {
@@ -28840,8 +29157,8 @@ function hasVenvModule() {
28840
29157
  }
28841
29158
  function ensureVenv(log) {
28842
29159
  const venvDir = getVenvDir();
28843
- const venvPip = join38(venvDir, "bin", "pip");
28844
- if (existsSync28(venvPip))
29160
+ const venvPip = join39(venvDir, "bin", "pip");
29161
+ if (existsSync29(venvPip))
28845
29162
  return venvDir;
28846
29163
  log("Creating Python venv for vision deps...");
28847
29164
  if (!hasCmd("python3")) {
@@ -28853,9 +29170,9 @@ function ensureVenv(log) {
28853
29170
  return null;
28854
29171
  }
28855
29172
  try {
28856
- mkdirSync9(join38(homedir10(), ".open-agents"), { recursive: true });
29173
+ mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
28857
29174
  execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
28858
- execSync25(`"${join38(venvDir, "bin", "pip")}" install --upgrade pip`, {
29175
+ execSync25(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
28859
29176
  stdio: "pipe",
28860
29177
  timeout: 6e4
28861
29178
  });
@@ -29064,15 +29381,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29064
29381
  }
29065
29382
  }
29066
29383
  const venvDir = getVenvDir();
29067
- const venvBin = join38(venvDir, "bin");
29068
- const venvMoondream = join38(venvBin, "moondream-station");
29384
+ const venvBin = join39(venvDir, "bin");
29385
+ const venvMoondream = join39(venvBin, "moondream-station");
29069
29386
  const venv = ensureVenv(log);
29070
- if (venv && !hasCmd("moondream-station") && !existsSync28(venvMoondream)) {
29071
- const venvPip = join38(venvBin, "pip");
29387
+ if (venv && !hasCmd("moondream-station") && !existsSync29(venvMoondream)) {
29388
+ const venvPip = join39(venvBin, "pip");
29072
29389
  log("Installing moondream-station in ~/.open-agents/venv...");
29073
29390
  try {
29074
29391
  execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
29075
- if (existsSync28(venvMoondream)) {
29392
+ if (existsSync29(venvMoondream)) {
29076
29393
  log("moondream-station installed successfully.");
29077
29394
  } else {
29078
29395
  try {
@@ -29089,8 +29406,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29089
29406
  }
29090
29407
  }
29091
29408
  if (venv) {
29092
- const venvPython = join38(venvBin, "python");
29093
- const venvPip2 = join38(venvBin, "pip");
29409
+ const venvPython = join39(venvBin, "python");
29410
+ const venvPip2 = join39(venvBin, "pip");
29094
29411
  let ocrStackInstalled = false;
29095
29412
  try {
29096
29413
  execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
@@ -29203,10 +29520,10 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
29203
29520
  `PARAMETER num_predict ${numPredict}`,
29204
29521
  `PARAMETER stop "<|endoftext|>"`
29205
29522
  ].join("\n");
29206
- const modelDir2 = join38(homedir10(), ".open-agents", "models");
29207
- mkdirSync9(modelDir2, { recursive: true });
29208
- const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
29209
- 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");
29210
29527
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
29211
29528
  stdio: "pipe",
29212
29529
  timeout: 12e4
@@ -30534,17 +30851,17 @@ async function handleUpdate(subcommand, ctx) {
30534
30851
  try {
30535
30852
  const { createRequire: createRequire4 } = await import("node:module");
30536
30853
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
30537
- const { dirname: dirname18, join: join53 } = await import("node:path");
30538
- 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");
30539
30856
  const req = createRequire4(import.meta.url);
30540
- const thisDir = dirname18(fileURLToPath14(import.meta.url));
30857
+ const thisDir = dirname19(fileURLToPath14(import.meta.url));
30541
30858
  const candidates = [
30542
- join53(thisDir, "..", "package.json"),
30543
- join53(thisDir, "..", "..", "package.json"),
30544
- join53(thisDir, "..", "..", "..", "package.json")
30859
+ join54(thisDir, "..", "package.json"),
30860
+ join54(thisDir, "..", "..", "package.json"),
30861
+ join54(thisDir, "..", "..", "..", "package.json")
30545
30862
  ];
30546
30863
  for (const pkgPath of candidates) {
30547
- if (existsSync39(pkgPath)) {
30864
+ if (existsSync40(pkgPath)) {
30548
30865
  const pkg = req(pkgPath);
30549
30866
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
30550
30867
  currentVersion = pkg.version ?? "0.0.0";
@@ -30819,8 +31136,8 @@ var init_commands = __esm({
30819
31136
  });
30820
31137
 
30821
31138
  // packages/cli/dist/tui/project-context.js
30822
- import { existsSync as existsSync29, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
30823
- 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";
30824
31141
  import { execSync as execSync26 } from "node:child_process";
30825
31142
  import { homedir as homedir11, platform as platform2, release } from "node:os";
30826
31143
  function getModelTier(modelName) {
@@ -30855,10 +31172,10 @@ function loadProjectMap(repoRoot) {
30855
31172
  if (!hasOaDirectory(repoRoot)) {
30856
31173
  initOaDirectory(repoRoot);
30857
31174
  }
30858
- const mapPath = join39(repoRoot, OA_DIR, "context", "project-map.md");
30859
- if (existsSync29(mapPath)) {
31175
+ const mapPath = join40(repoRoot, OA_DIR, "context", "project-map.md");
31176
+ if (existsSync30(mapPath)) {
30860
31177
  try {
30861
- const content = readFileSync20(mapPath, "utf-8");
31178
+ const content = readFileSync21(mapPath, "utf-8");
30862
31179
  return content;
30863
31180
  } catch {
30864
31181
  }
@@ -30899,31 +31216,31 @@ ${log}`);
30899
31216
  }
30900
31217
  function loadMemoryContext(repoRoot) {
30901
31218
  const sections = [];
30902
- const oaMemDir = join39(repoRoot, OA_DIR, "memory");
31219
+ const oaMemDir = join40(repoRoot, OA_DIR, "memory");
30903
31220
  const oaEntries = loadMemoryDir(oaMemDir, "project");
30904
31221
  if (oaEntries)
30905
31222
  sections.push(oaEntries);
30906
- const legacyMemDir = join39(repoRoot, ".open-agents", "memory");
30907
- if (legacyMemDir !== oaMemDir && existsSync29(legacyMemDir)) {
31223
+ const legacyMemDir = join40(repoRoot, ".open-agents", "memory");
31224
+ if (legacyMemDir !== oaMemDir && existsSync30(legacyMemDir)) {
30908
31225
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
30909
31226
  if (legacyEntries)
30910
31227
  sections.push(legacyEntries);
30911
31228
  }
30912
- const globalMemDir = join39(homedir11(), ".open-agents", "memory");
31229
+ const globalMemDir = join40(homedir11(), ".open-agents", "memory");
30913
31230
  const globalEntries = loadMemoryDir(globalMemDir, "global");
30914
31231
  if (globalEntries)
30915
31232
  sections.push(globalEntries);
30916
31233
  return sections.join("\n\n");
30917
31234
  }
30918
31235
  function loadMemoryDir(memDir, scope) {
30919
- if (!existsSync29(memDir))
31236
+ if (!existsSync30(memDir))
30920
31237
  return "";
30921
31238
  const lines = [];
30922
31239
  try {
30923
31240
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
30924
31241
  for (const file of files.slice(0, 10)) {
30925
31242
  try {
30926
- const raw = readFileSync20(join39(memDir, file), "utf-8");
31243
+ const raw = readFileSync21(join40(memDir, file), "utf-8");
30927
31244
  const entries = JSON.parse(raw);
30928
31245
  const topic = basename10(file, ".json");
30929
31246
  const keys = Object.keys(entries);
@@ -31950,22 +32267,22 @@ var init_carousel = __esm({
31950
32267
  });
31951
32268
 
31952
32269
  // packages/cli/dist/tui/carousel-descriptors.js
31953
- import { existsSync as existsSync30, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
31954
- 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";
31955
32272
  function loadToolProfile(repoRoot) {
31956
- const filePath = join40(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
32273
+ const filePath = join41(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
31957
32274
  try {
31958
- if (!existsSync30(filePath))
32275
+ if (!existsSync31(filePath))
31959
32276
  return null;
31960
- return JSON.parse(readFileSync21(filePath, "utf-8"));
32277
+ return JSON.parse(readFileSync22(filePath, "utf-8"));
31961
32278
  } catch {
31962
32279
  return null;
31963
32280
  }
31964
32281
  }
31965
32282
  function saveToolProfile(repoRoot, profile) {
31966
- const contextDir = join40(repoRoot, OA_DIR, "context");
31967
- mkdirSync10(contextDir, { recursive: true });
31968
- 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");
31969
32286
  }
31970
32287
  function categorizeToolCall(toolName) {
31971
32288
  for (const cat of TOOL_CATEGORIES) {
@@ -32023,25 +32340,25 @@ function weightedColor(profile) {
32023
32340
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
32024
32341
  }
32025
32342
  function loadCachedDescriptors(repoRoot) {
32026
- const filePath = join40(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
32343
+ const filePath = join41(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
32027
32344
  try {
32028
- if (!existsSync30(filePath))
32345
+ if (!existsSync31(filePath))
32029
32346
  return null;
32030
- const cached = JSON.parse(readFileSync21(filePath, "utf-8"));
32347
+ const cached = JSON.parse(readFileSync22(filePath, "utf-8"));
32031
32348
  return cached.phrases.length > 0 ? cached.phrases : null;
32032
32349
  } catch {
32033
32350
  return null;
32034
32351
  }
32035
32352
  }
32036
32353
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
32037
- const contextDir = join40(repoRoot, OA_DIR, "context");
32038
- mkdirSync10(contextDir, { recursive: true });
32354
+ const contextDir = join41(repoRoot, OA_DIR, "context");
32355
+ mkdirSync11(contextDir, { recursive: true });
32039
32356
  const cached = {
32040
32357
  phrases,
32041
32358
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
32042
32359
  sourceHash
32043
32360
  };
32044
- 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");
32045
32362
  }
32046
32363
  function generateDescriptors(repoRoot) {
32047
32364
  const profile = loadToolProfile(repoRoot);
@@ -32089,11 +32406,11 @@ function generateDescriptors(repoRoot) {
32089
32406
  return phrases;
32090
32407
  }
32091
32408
  function extractFromPackageJson(repoRoot, tags) {
32092
- const pkgPath = join40(repoRoot, "package.json");
32409
+ const pkgPath = join41(repoRoot, "package.json");
32093
32410
  try {
32094
- if (!existsSync30(pkgPath))
32411
+ if (!existsSync31(pkgPath))
32095
32412
  return;
32096
- const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
32413
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
32097
32414
  if (pkg.name && typeof pkg.name === "string") {
32098
32415
  const parts = pkg.name.replace(/^@/, "").split("/");
32099
32416
  for (const p of parts)
@@ -32137,7 +32454,7 @@ function extractFromManifests(repoRoot, tags) {
32137
32454
  { file: ".github/workflows", tag: "ci/cd" }
32138
32455
  ];
32139
32456
  for (const check of manifestChecks) {
32140
- if (existsSync30(join40(repoRoot, check.file))) {
32457
+ if (existsSync31(join41(repoRoot, check.file))) {
32141
32458
  tags.push(check.tag);
32142
32459
  }
32143
32460
  }
@@ -32159,16 +32476,16 @@ function extractFromSessions(repoRoot, tags) {
32159
32476
  }
32160
32477
  }
32161
32478
  function extractFromMemory(repoRoot, tags) {
32162
- const memoryDir = join40(repoRoot, OA_DIR, "memory");
32479
+ const memoryDir = join41(repoRoot, OA_DIR, "memory");
32163
32480
  try {
32164
- if (!existsSync30(memoryDir))
32481
+ if (!existsSync31(memoryDir))
32165
32482
  return;
32166
32483
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
32167
32484
  for (const file of files) {
32168
32485
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
32169
32486
  tags.push(topic);
32170
32487
  try {
32171
- const data = JSON.parse(readFileSync21(join40(memoryDir, file), "utf-8"));
32488
+ const data = JSON.parse(readFileSync22(join41(memoryDir, file), "utf-8"));
32172
32489
  if (data && typeof data === "object") {
32173
32490
  const keys = Object.keys(data).slice(0, 3);
32174
32491
  for (const key of keys) {
@@ -32303,25 +32620,25 @@ var init_carousel_descriptors = __esm({
32303
32620
  });
32304
32621
 
32305
32622
  // packages/cli/dist/tui/voice.js
32306
- import { existsSync as existsSync31, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
32307
- 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";
32308
32625
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
32309
32626
  import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
32310
32627
  import { createRequire } from "node:module";
32311
32628
  function voiceDir() {
32312
- return join41(homedir12(), ".open-agents", "voice");
32629
+ return join42(homedir12(), ".open-agents", "voice");
32313
32630
  }
32314
32631
  function modelsDir() {
32315
- return join41(voiceDir(), "models");
32632
+ return join42(voiceDir(), "models");
32316
32633
  }
32317
32634
  function modelDir(id) {
32318
- return join41(modelsDir(), id);
32635
+ return join42(modelsDir(), id);
32319
32636
  }
32320
32637
  function modelOnnxPath(id) {
32321
- return join41(modelDir(id), "model.onnx");
32638
+ return join42(modelDir(id), "model.onnx");
32322
32639
  }
32323
32640
  function modelConfigPath(id) {
32324
- return join41(modelDir(id), "config.json");
32641
+ return join42(modelDir(id), "config.json");
32325
32642
  }
32326
32643
  function emotionToPitchBias(emotion) {
32327
32644
  const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
@@ -33141,7 +33458,7 @@ var init_voice = __esm({
33141
33458
  }
33142
33459
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
33143
33460
  }
33144
- const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
33461
+ const wavPath = join42(tmpdir6(), `oa-voice-${Date.now()}.wav`);
33145
33462
  this.writeWav(audioData, sampleRate, wavPath);
33146
33463
  await this.playWav(wavPath);
33147
33464
  try {
@@ -33273,7 +33590,7 @@ var init_voice = __esm({
33273
33590
  return buffer;
33274
33591
  }
33275
33592
  writeWav(samples, sampleRate, path) {
33276
- writeFileSync11(path, this.buildWavBuffer(samples, sampleRate));
33593
+ writeFileSync12(path, this.buildWavBuffer(samples, sampleRate));
33277
33594
  }
33278
33595
  // -------------------------------------------------------------------------
33279
33596
  // Audio playback (system default speakers)
@@ -33432,7 +33749,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33432
33749
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
33433
33750
  const mlxVoice = model.mlxVoice ?? "af_heart";
33434
33751
  const mlxLangCode = model.mlxLangCode ?? "a";
33435
- const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
33752
+ const wavPath = join42(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
33436
33753
  const pyScript = [
33437
33754
  "import sys, json",
33438
33755
  "from mlx_audio.tts import generate as tts_gen",
@@ -33449,11 +33766,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33449
33766
  return;
33450
33767
  }
33451
33768
  }
33452
- if (!existsSync31(wavPath))
33769
+ if (!existsSync32(wavPath))
33453
33770
  return;
33454
33771
  if (volume !== 1) {
33455
33772
  try {
33456
- const wavData = readFileSync22(wavPath);
33773
+ const wavData = readFileSync23(wavPath);
33457
33774
  if (wavData.length > 44) {
33458
33775
  const header = wavData.subarray(0, 44);
33459
33776
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -33461,14 +33778,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33461
33778
  samples[i] = Math.round(samples[i] * volume);
33462
33779
  }
33463
33780
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
33464
- writeFileSync11(wavPath, scaled);
33781
+ writeFileSync12(wavPath, scaled);
33465
33782
  }
33466
33783
  } catch {
33467
33784
  }
33468
33785
  }
33469
33786
  if (this.onPCMOutput) {
33470
33787
  try {
33471
- const wavData = readFileSync22(wavPath);
33788
+ const wavData = readFileSync23(wavPath);
33472
33789
  if (wavData.length > 44) {
33473
33790
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
33474
33791
  const sampleRate = wavData.readUInt32LE(24);
@@ -33500,7 +33817,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33500
33817
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
33501
33818
  const mlxVoice = model.mlxVoice ?? "af_heart";
33502
33819
  const mlxLangCode = model.mlxLangCode ?? "a";
33503
- const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
33820
+ const wavPath = join42(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
33504
33821
  const pyScript = [
33505
33822
  "import sys, json",
33506
33823
  "from mlx_audio.tts import generate as tts_gen",
@@ -33517,10 +33834,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33517
33834
  return null;
33518
33835
  }
33519
33836
  }
33520
- if (!existsSync31(wavPath))
33837
+ if (!existsSync32(wavPath))
33521
33838
  return null;
33522
33839
  try {
33523
- const data = readFileSync22(wavPath);
33840
+ const data = readFileSync23(wavPath);
33524
33841
  unlinkSync4(wavPath);
33525
33842
  return data;
33526
33843
  } catch {
@@ -33534,41 +33851,41 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
33534
33851
  if (this.ort)
33535
33852
  return;
33536
33853
  const arch = process.arch;
33537
- mkdirSync11(voiceDir(), { recursive: true });
33538
- const pkgPath = join41(voiceDir(), "package.json");
33854
+ mkdirSync12(voiceDir(), { recursive: true });
33855
+ const pkgPath = join42(voiceDir(), "package.json");
33539
33856
  const expectedDeps = {
33540
33857
  "onnxruntime-node": "^1.21.0",
33541
33858
  "phonemizer": "^1.2.1"
33542
33859
  };
33543
- if (existsSync31(pkgPath)) {
33860
+ if (existsSync32(pkgPath)) {
33544
33861
  try {
33545
- const existing = JSON.parse(readFileSync22(pkgPath, "utf8"));
33862
+ const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
33546
33863
  if (!existing.dependencies?.["phonemizer"]) {
33547
33864
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
33548
- writeFileSync11(pkgPath, JSON.stringify(existing, null, 2));
33865
+ writeFileSync12(pkgPath, JSON.stringify(existing, null, 2));
33549
33866
  }
33550
33867
  } catch {
33551
33868
  }
33552
33869
  }
33553
- if (!existsSync31(pkgPath)) {
33554
- writeFileSync11(pkgPath, JSON.stringify({
33870
+ if (!existsSync32(pkgPath)) {
33871
+ writeFileSync12(pkgPath, JSON.stringify({
33555
33872
  name: "open-agents-voice",
33556
33873
  private: true,
33557
33874
  dependencies: expectedDeps
33558
33875
  }, null, 2));
33559
33876
  }
33560
- const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
33877
+ const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
33561
33878
  const probeOnnx = () => {
33562
33879
  try {
33563
- 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") } });
33564
33881
  const output = result.toString().trim();
33565
33882
  return output === "OK";
33566
33883
  } catch {
33567
33884
  return false;
33568
33885
  }
33569
33886
  };
33570
- const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
33571
- const onnxInstalled = existsSync31(onnxNodeModules);
33887
+ const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
33888
+ const onnxInstalled = existsSync32(onnxNodeModules);
33572
33889
  if (onnxInstalled && !probeOnnx()) {
33573
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.`);
33574
33891
  }
@@ -33626,18 +33943,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33626
33943
  const dir = modelDir(id);
33627
33944
  const onnxPath = modelOnnxPath(id);
33628
33945
  const configPath = modelConfigPath(id);
33629
- if (existsSync31(onnxPath) && existsSync31(configPath))
33946
+ if (existsSync32(onnxPath) && existsSync32(configPath))
33630
33947
  return;
33631
- mkdirSync11(dir, { recursive: true });
33632
- if (!existsSync31(configPath)) {
33948
+ mkdirSync12(dir, { recursive: true });
33949
+ if (!existsSync32(configPath)) {
33633
33950
  renderInfo(`Downloading ${model.label} voice config...`);
33634
33951
  const configResp = await fetch(model.configUrl);
33635
33952
  if (!configResp.ok)
33636
33953
  throw new Error(`Failed to download config: HTTP ${configResp.status}`);
33637
33954
  const configText = await configResp.text();
33638
- writeFileSync11(configPath, configText);
33955
+ writeFileSync12(configPath, configText);
33639
33956
  }
33640
- if (!existsSync31(onnxPath)) {
33957
+ if (!existsSync32(onnxPath)) {
33641
33958
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
33642
33959
  const onnxResp = await fetch(model.onnxUrl);
33643
33960
  if (!onnxResp.ok)
@@ -33662,7 +33979,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33662
33979
  }
33663
33980
  }
33664
33981
  const fullBuffer = Buffer.concat(chunks);
33665
- writeFileSync11(onnxPath, fullBuffer);
33982
+ writeFileSync12(onnxPath, fullBuffer);
33666
33983
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
33667
33984
  }
33668
33985
  }
@@ -33674,10 +33991,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
33674
33991
  throw new Error("ONNX runtime not loaded");
33675
33992
  const onnxPath = modelOnnxPath(this.modelId);
33676
33993
  const configPath = modelConfigPath(this.modelId);
33677
- if (!existsSync31(onnxPath) || !existsSync31(configPath)) {
33994
+ if (!existsSync32(onnxPath) || !existsSync32(configPath)) {
33678
33995
  throw new Error(`Model files not found for ${this.modelId}`);
33679
33996
  }
33680
- this.config = JSON.parse(readFileSync22(configPath, "utf8"));
33997
+ this.config = JSON.parse(readFileSync23(configPath, "utf8"));
33681
33998
  this.session = await this.ort.InferenceSession.create(onnxPath, {
33682
33999
  executionProviders: ["cpu"],
33683
34000
  graphOptimizationLevel: "all"
@@ -34538,13 +34855,13 @@ var init_stream_renderer = __esm({
34538
34855
  });
34539
34856
 
34540
34857
  // packages/cli/dist/tui/edit-history.js
34541
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
34542
- 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";
34543
34860
  function createEditHistoryLogger(repoRoot, sessionId) {
34544
- const historyDir = join42(repoRoot, ".oa", "history");
34545
- const logPath = join42(historyDir, "edits.jsonl");
34861
+ const historyDir = join43(repoRoot, ".oa", "history");
34862
+ const logPath = join43(historyDir, "edits.jsonl");
34546
34863
  try {
34547
- mkdirSync12(historyDir, { recursive: true });
34864
+ mkdirSync13(historyDir, { recursive: true });
34548
34865
  } catch {
34549
34866
  }
34550
34867
  function logToolCall(toolName, toolArgs, success) {
@@ -34653,46 +34970,46 @@ var init_edit_history = __esm({
34653
34970
  });
34654
34971
 
34655
34972
  // packages/cli/dist/tui/promptLoader.js
34656
- import { readFileSync as readFileSync23, existsSync as existsSync32 } from "node:fs";
34657
- 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";
34658
34975
  import { fileURLToPath as fileURLToPath11 } from "node:url";
34659
34976
  function loadPrompt3(promptPath, vars) {
34660
34977
  let content = cache3.get(promptPath);
34661
34978
  if (content === void 0) {
34662
- const fullPath = join43(PROMPTS_DIR3, promptPath);
34663
- if (!existsSync32(fullPath)) {
34979
+ const fullPath = join44(PROMPTS_DIR3, promptPath);
34980
+ if (!existsSync33(fullPath)) {
34664
34981
  throw new Error(`Prompt file not found: ${fullPath}`);
34665
34982
  }
34666
- content = readFileSync23(fullPath, "utf-8");
34983
+ content = readFileSync24(fullPath, "utf-8");
34667
34984
  cache3.set(promptPath, content);
34668
34985
  }
34669
34986
  if (!vars)
34670
34987
  return content;
34671
34988
  return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
34672
34989
  }
34673
- var __filename3, __dirname5, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
34990
+ var __filename3, __dirname6, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
34674
34991
  var init_promptLoader3 = __esm({
34675
34992
  "packages/cli/dist/tui/promptLoader.js"() {
34676
34993
  "use strict";
34677
34994
  __filename3 = fileURLToPath11(import.meta.url);
34678
- __dirname5 = dirname15(__filename3);
34679
- devPath2 = join43(__dirname5, "..", "..", "prompts");
34680
- publishedPath2 = join43(__dirname5, "..", "prompts");
34681
- 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;
34682
34999
  cache3 = /* @__PURE__ */ new Map();
34683
35000
  }
34684
35001
  });
34685
35002
 
34686
35003
  // packages/cli/dist/tui/dream-engine.js
34687
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync33, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
34688
- 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";
34689
35006
  import { execSync as execSync28 } from "node:child_process";
34690
35007
  function loadAutoresearchMemory(repoRoot) {
34691
- const memoryPath = join44(repoRoot, ".oa", "memory", "autoresearch.json");
34692
- if (!existsSync33(memoryPath))
35008
+ const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
35009
+ if (!existsSync34(memoryPath))
34693
35010
  return "";
34694
35011
  try {
34695
- const raw = readFileSync24(memoryPath, "utf-8");
35012
+ const raw = readFileSync25(memoryPath, "utf-8");
34696
35013
  const data = JSON.parse(raw);
34697
35014
  const sections = [];
34698
35015
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -34882,14 +35199,14 @@ var init_dream_engine = __esm({
34882
35199
  const content = String(args["content"] ?? "");
34883
35200
  if (!rawPath)
34884
35201
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34885
- 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);
34886
35203
  if (!targetPath.startsWith(this.autoresearchDir)) {
34887
35204
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34888
35205
  }
34889
35206
  try {
34890
- const dir = join44(targetPath, "..");
34891
- mkdirSync13(dir, { recursive: true });
34892
- writeFileSync12(targetPath, content, "utf-8");
35207
+ const dir = join45(targetPath, "..");
35208
+ mkdirSync14(dir, { recursive: true });
35209
+ writeFileSync13(targetPath, content, "utf-8");
34893
35210
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
34894
35211
  } catch (err) {
34895
35212
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34917,20 +35234,20 @@ var init_dream_engine = __esm({
34917
35234
  const rawPath = String(args["path"] ?? "");
34918
35235
  const oldStr = String(args["old_string"] ?? "");
34919
35236
  const newStr = String(args["new_string"] ?? "");
34920
- 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);
34921
35238
  if (!targetPath.startsWith(this.autoresearchDir)) {
34922
35239
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34923
35240
  }
34924
35241
  try {
34925
- if (!existsSync33(targetPath)) {
35242
+ if (!existsSync34(targetPath)) {
34926
35243
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
34927
35244
  }
34928
- let content = readFileSync24(targetPath, "utf-8");
35245
+ let content = readFileSync25(targetPath, "utf-8");
34929
35246
  if (!content.includes(oldStr)) {
34930
35247
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
34931
35248
  }
34932
35249
  content = content.replace(oldStr, newStr);
34933
- writeFileSync12(targetPath, content, "utf-8");
35250
+ writeFileSync13(targetPath, content, "utf-8");
34934
35251
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
34935
35252
  } catch (err) {
34936
35253
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -34971,14 +35288,14 @@ var init_dream_engine = __esm({
34971
35288
  const content = String(args["content"] ?? "");
34972
35289
  if (!rawPath)
34973
35290
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34974
- 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);
34975
35292
  if (!targetPath.startsWith(this.dreamsDir)) {
34976
35293
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
34977
35294
  }
34978
35295
  try {
34979
- const dir = join44(targetPath, "..");
34980
- mkdirSync13(dir, { recursive: true });
34981
- writeFileSync12(targetPath, content, "utf-8");
35296
+ const dir = join45(targetPath, "..");
35297
+ mkdirSync14(dir, { recursive: true });
35298
+ writeFileSync13(targetPath, content, "utf-8");
34982
35299
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
34983
35300
  } catch (err) {
34984
35301
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -35006,20 +35323,20 @@ var init_dream_engine = __esm({
35006
35323
  const rawPath = String(args["path"] ?? "");
35007
35324
  const oldStr = String(args["old_string"] ?? "");
35008
35325
  const newStr = String(args["new_string"] ?? "");
35009
- 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);
35010
35327
  if (!targetPath.startsWith(this.dreamsDir)) {
35011
35328
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
35012
35329
  }
35013
35330
  try {
35014
- if (!existsSync33(targetPath)) {
35331
+ if (!existsSync34(targetPath)) {
35015
35332
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
35016
35333
  }
35017
- let content = readFileSync24(targetPath, "utf-8");
35334
+ let content = readFileSync25(targetPath, "utf-8");
35018
35335
  if (!content.includes(oldStr)) {
35019
35336
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
35020
35337
  }
35021
35338
  content = content.replace(oldStr, newStr);
35022
- writeFileSync12(targetPath, content, "utf-8");
35339
+ writeFileSync13(targetPath, content, "utf-8");
35023
35340
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
35024
35341
  } catch (err) {
35025
35342
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
@@ -35073,7 +35390,7 @@ var init_dream_engine = __esm({
35073
35390
  constructor(config, repoRoot) {
35074
35391
  this.config = config;
35075
35392
  this.repoRoot = repoRoot;
35076
- this.dreamsDir = join44(repoRoot, ".oa", "dreams");
35393
+ this.dreamsDir = join45(repoRoot, ".oa", "dreams");
35077
35394
  this.state = {
35078
35395
  mode: "default",
35079
35396
  active: false,
@@ -35104,7 +35421,7 @@ var init_dream_engine = __esm({
35104
35421
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
35105
35422
  results: []
35106
35423
  };
35107
- mkdirSync13(this.dreamsDir, { recursive: true });
35424
+ mkdirSync14(this.dreamsDir, { recursive: true });
35108
35425
  this.saveDreamState();
35109
35426
  try {
35110
35427
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -35157,8 +35474,8 @@ ${result.summary}`;
35157
35474
  if (mode !== "default" || cycle === totalCycles) {
35158
35475
  renderDreamContraction(cycle);
35159
35476
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
35160
- const summaryPath = join44(this.dreamsDir, `cycle-${cycle}-summary.md`);
35161
- writeFileSync12(summaryPath, cycleSummary, "utf-8");
35477
+ const summaryPath = join45(this.dreamsDir, `cycle-${cycle}-summary.md`);
35478
+ writeFileSync13(summaryPath, cycleSummary, "utf-8");
35162
35479
  }
35163
35480
  if (mode === "lucid" && !this.abortController.signal.aborted) {
35164
35481
  this.saveVersionCheckpoint(cycle);
@@ -35370,7 +35687,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
35370
35687
  }
35371
35688
  /** Build role-specific tool sets for swarm agents */
35372
35689
  buildSwarmTools(role, _workspace) {
35373
- const autoresearchDir = join44(this.repoRoot, ".oa", "autoresearch");
35690
+ const autoresearchDir = join45(this.repoRoot, ".oa", "autoresearch");
35374
35691
  const taskComplete = this.createSwarmTaskCompleteTool(role);
35375
35692
  switch (role) {
35376
35693
  case "researcher": {
@@ -35734,7 +36051,7 @@ INSTRUCTIONS:
35734
36051
  2. Summarize the key learnings and next steps
35735
36052
 
35736
36053
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
35737
- const reportPath = join44(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
36054
+ const reportPath = join45(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
35738
36055
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
35739
36056
 
35740
36057
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -35756,8 +36073,8 @@ ${summaryResult}
35756
36073
  *Generated by open-agents autoresearch swarm*
35757
36074
  `;
35758
36075
  try {
35759
- mkdirSync13(this.dreamsDir, { recursive: true });
35760
- writeFileSync12(reportPath, report, "utf-8");
36076
+ mkdirSync14(this.dreamsDir, { recursive: true });
36077
+ writeFileSync13(reportPath, report, "utf-8");
35761
36078
  } catch {
35762
36079
  }
35763
36080
  renderSwarmComplete(workspace);
@@ -35823,9 +36140,9 @@ ${summaryResult}
35823
36140
  }
35824
36141
  /** Save workspace backup for lucid mode */
35825
36142
  saveVersionCheckpoint(cycle) {
35826
- const checkpointDir = join44(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
36143
+ const checkpointDir = join45(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
35827
36144
  try {
35828
- mkdirSync13(checkpointDir, { recursive: true });
36145
+ mkdirSync14(checkpointDir, { recursive: true });
35829
36146
  try {
35830
36147
  const gitStatus = execSync28("git status --porcelain", {
35831
36148
  cwd: this.repoRoot,
@@ -35842,10 +36159,10 @@ ${summaryResult}
35842
36159
  encoding: "utf-8",
35843
36160
  timeout: 5e3
35844
36161
  }).trim();
35845
- writeFileSync12(join44(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
35846
- writeFileSync12(join44(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
35847
- writeFileSync12(join44(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
35848
- 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({
35849
36166
  cycle,
35850
36167
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
35851
36168
  gitHash,
@@ -35853,7 +36170,7 @@ ${summaryResult}
35853
36170
  }, null, 2), "utf-8");
35854
36171
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
35855
36172
  } catch {
35856
- 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");
35857
36174
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
35858
36175
  }
35859
36176
  } catch (err) {
@@ -35911,14 +36228,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
35911
36228
  ---
35912
36229
  *Auto-generated by open-agents dream engine*
35913
36230
  `;
35914
- writeFileSync12(join44(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
36231
+ writeFileSync13(join45(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
35915
36232
  } catch {
35916
36233
  }
35917
36234
  }
35918
36235
  /** Save dream state for resume/inspection */
35919
36236
  saveDreamState() {
35920
36237
  try {
35921
- 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");
35922
36239
  } catch {
35923
36240
  }
35924
36241
  }
@@ -36292,8 +36609,8 @@ var init_bless_engine = __esm({
36292
36609
  });
36293
36610
 
36294
36611
  // packages/cli/dist/tui/dmn-engine.js
36295
- import { existsSync as existsSync34, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
36296
- 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";
36297
36614
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
36298
36615
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
36299
36616
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -36406,9 +36723,9 @@ var init_dmn_engine = __esm({
36406
36723
  constructor(config, repoRoot) {
36407
36724
  this.config = config;
36408
36725
  this.repoRoot = repoRoot;
36409
- this.stateDir = join45(repoRoot, ".oa", "dmn");
36410
- this.historyDir = join45(repoRoot, ".oa", "dmn", "cycles");
36411
- 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 });
36412
36729
  this.loadState();
36413
36730
  }
36414
36731
  get stats() {
@@ -36997,11 +37314,11 @@ OUTPUT: Call task_complete with JSON:
36997
37314
  async gatherMemoryTopics() {
36998
37315
  const topics = [];
36999
37316
  const dirs = [
37000
- join45(this.repoRoot, ".oa", "memory"),
37001
- join45(this.repoRoot, ".open-agents", "memory")
37317
+ join46(this.repoRoot, ".oa", "memory"),
37318
+ join46(this.repoRoot, ".open-agents", "memory")
37002
37319
  ];
37003
37320
  for (const dir of dirs) {
37004
- if (!existsSync34(dir))
37321
+ if (!existsSync35(dir))
37005
37322
  continue;
37006
37323
  try {
37007
37324
  const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
@@ -37017,29 +37334,29 @@ OUTPUT: Call task_complete with JSON:
37017
37334
  }
37018
37335
  // ── State persistence ─────────────────────────────────────────────────
37019
37336
  loadState() {
37020
- const path = join45(this.stateDir, "state.json");
37021
- if (existsSync34(path)) {
37337
+ const path = join46(this.stateDir, "state.json");
37338
+ if (existsSync35(path)) {
37022
37339
  try {
37023
- this.state = JSON.parse(readFileSync25(path, "utf-8"));
37340
+ this.state = JSON.parse(readFileSync26(path, "utf-8"));
37024
37341
  } catch {
37025
37342
  }
37026
37343
  }
37027
37344
  }
37028
37345
  saveState() {
37029
37346
  try {
37030
- 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");
37031
37348
  } catch {
37032
37349
  }
37033
37350
  }
37034
37351
  saveCycleResult(result) {
37035
37352
  try {
37036
37353
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
37037
- 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");
37038
37355
  const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
37039
37356
  if (files.length > 50) {
37040
37357
  for (const old of files.slice(0, files.length - 50)) {
37041
37358
  try {
37042
- unlinkSync5(join45(this.historyDir, old));
37359
+ unlinkSync5(join46(this.historyDir, old));
37043
37360
  } catch {
37044
37361
  }
37045
37362
  }
@@ -37052,8 +37369,8 @@ OUTPUT: Call task_complete with JSON:
37052
37369
  });
37053
37370
 
37054
37371
  // packages/cli/dist/tui/snr-engine.js
37055
- import { existsSync as existsSync35, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
37056
- 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";
37057
37374
  function computeDPrime(signalScores, noiseScores) {
37058
37375
  if (signalScores.length === 0 || noiseScores.length === 0)
37059
37376
  return 0;
@@ -37293,11 +37610,11 @@ Call task_complete with the JSON array when done.`, onEvent)
37293
37610
  loadMemoryEntries(topics) {
37294
37611
  const entries = [];
37295
37612
  const dirs = [
37296
- join46(this.repoRoot, ".oa", "memory"),
37297
- join46(this.repoRoot, ".open-agents", "memory")
37613
+ join47(this.repoRoot, ".oa", "memory"),
37614
+ join47(this.repoRoot, ".open-agents", "memory")
37298
37615
  ];
37299
37616
  for (const dir of dirs) {
37300
- if (!existsSync35(dir))
37617
+ if (!existsSync36(dir))
37301
37618
  continue;
37302
37619
  try {
37303
37620
  const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
@@ -37306,7 +37623,7 @@ Call task_complete with the JSON array when done.`, onEvent)
37306
37623
  if (topics.length > 0 && !topics.includes(topic))
37307
37624
  continue;
37308
37625
  try {
37309
- const data = JSON.parse(readFileSync26(join46(dir, f), "utf-8"));
37626
+ const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
37310
37627
  for (const [key, val] of Object.entries(data)) {
37311
37628
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
37312
37629
  entries.push({ topic, key, value });
@@ -37857,8 +38174,8 @@ var init_tool_policy = __esm({
37857
38174
  });
37858
38175
 
37859
38176
  // packages/cli/dist/tui/telegram-bridge.js
37860
- import { mkdirSync as mkdirSync15, existsSync as existsSync36, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
37861
- 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";
37862
38179
  import { writeFile as writeFileAsync } from "node:fs/promises";
37863
38180
  function convertMarkdownToTelegramHTML(md) {
37864
38181
  let html = md;
@@ -38186,7 +38503,7 @@ with summary "no_reply" to silently skip without responding.
38186
38503
  this.polling = true;
38187
38504
  this.abortController = new AbortController();
38188
38505
  try {
38189
- mkdirSync15(this.mediaCacheDir, { recursive: true });
38506
+ mkdirSync16(this.mediaCacheDir, { recursive: true });
38190
38507
  } catch {
38191
38508
  }
38192
38509
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -38623,7 +38940,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
38623
38940
  return null;
38624
38941
  const buffer = Buffer.from(await res.arrayBuffer());
38625
38942
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
38626
- const localPath = join47(this.mediaCacheDir, fileName);
38943
+ const localPath = join48(this.mediaCacheDir, fileName);
38627
38944
  await writeFileAsync(localPath, buffer);
38628
38945
  return localPath;
38629
38946
  } catch {
@@ -40360,11 +40677,11 @@ var init_status_bar = __esm({
40360
40677
  import * as readline2 from "node:readline";
40361
40678
  import { Writable } from "node:stream";
40362
40679
  import { cwd } from "node:process";
40363
- 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";
40364
40681
  import { createRequire as createRequire2 } from "node:module";
40365
40682
  import { fileURLToPath as fileURLToPath12 } from "node:url";
40366
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync14, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync16 } from "node:fs";
40367
- 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";
40368
40685
  import { homedir as homedir13 } from "node:os";
40369
40686
  function formatTimeAgo(date) {
40370
40687
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -40382,14 +40699,14 @@ function formatTimeAgo(date) {
40382
40699
  function getVersion3() {
40383
40700
  try {
40384
40701
  const require2 = createRequire2(import.meta.url);
40385
- const thisDir = dirname16(fileURLToPath12(import.meta.url));
40702
+ const thisDir = dirname17(fileURLToPath12(import.meta.url));
40386
40703
  const candidates = [
40387
- join48(thisDir, "..", "package.json"),
40388
- join48(thisDir, "..", "..", "package.json"),
40389
- join48(thisDir, "..", "..", "..", "package.json")
40704
+ join49(thisDir, "..", "package.json"),
40705
+ join49(thisDir, "..", "..", "package.json"),
40706
+ join49(thisDir, "..", "..", "..", "package.json")
40390
40707
  ];
40391
40708
  for (const pkgPath of candidates) {
40392
- if (existsSync37(pkgPath)) {
40709
+ if (existsSync38(pkgPath)) {
40393
40710
  const pkg = require2(pkgPath);
40394
40711
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
40395
40712
  return pkg.version ?? "0.0.0";
@@ -40595,15 +40912,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
40595
40912
  function gatherMemorySnippets(root) {
40596
40913
  const snippets = [];
40597
40914
  const dirs = [
40598
- join48(root, ".oa", "memory"),
40599
- join48(root, ".open-agents", "memory")
40915
+ join49(root, ".oa", "memory"),
40916
+ join49(root, ".open-agents", "memory")
40600
40917
  ];
40601
40918
  for (const dir of dirs) {
40602
- if (!existsSync37(dir))
40919
+ if (!existsSync38(dir))
40603
40920
  continue;
40604
40921
  try {
40605
40922
  for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
40606
- const data = JSON.parse(readFileSync27(join48(dir, f), "utf-8"));
40923
+ const data = JSON.parse(readFileSync28(join49(dir, f), "utf-8"));
40607
40924
  for (const val of Object.values(data)) {
40608
40925
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
40609
40926
  if (v.length > 10)
@@ -40778,6 +41095,19 @@ ${entry.fullContent}`
40778
41095
  };
40779
41096
  }
40780
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
+ }
40781
41111
  if (slashCommandHandler) {
40782
41112
  runner.registerTool({
40783
41113
  name: "slash_command",
@@ -41338,7 +41668,7 @@ async function startInteractive(config, repoPath) {
41338
41668
  let exposeGateway = null;
41339
41669
  let peerMesh = null;
41340
41670
  let inferenceRouter = null;
41341
- const secretVault = new SecretVault(join48(repoRoot, ".oa", "vault.enc"));
41671
+ const secretVault = new SecretVault(join49(repoRoot, ".oa", "vault.enc"));
41342
41672
  let adminSessionKey = null;
41343
41673
  const callSubAgents = /* @__PURE__ */ new Map();
41344
41674
  const streamRenderer = new StreamRenderer();
@@ -41543,13 +41873,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
41543
41873
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
41544
41874
  return [hits, line];
41545
41875
  }
41546
- const HISTORY_DIR = join48(homedir13(), ".open-agents");
41547
- 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");
41548
41878
  const MAX_HISTORY_LINES = 500;
41549
41879
  let savedHistory = [];
41550
41880
  try {
41551
- if (existsSync37(HISTORY_FILE)) {
41552
- const raw = readFileSync27(HISTORY_FILE, "utf8").trim();
41881
+ if (existsSync38(HISTORY_FILE)) {
41882
+ const raw = readFileSync28(HISTORY_FILE, "utf8").trim();
41553
41883
  if (raw)
41554
41884
  savedHistory = raw.split("\n").reverse();
41555
41885
  }
@@ -41568,12 +41898,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
41568
41898
  if (!line.trim())
41569
41899
  return;
41570
41900
  try {
41571
- mkdirSync16(HISTORY_DIR, { recursive: true });
41901
+ mkdirSync17(HISTORY_DIR, { recursive: true });
41572
41902
  appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
41573
41903
  if (Math.random() < 0.02) {
41574
- const all = readFileSync27(HISTORY_FILE, "utf8").trim().split("\n");
41904
+ const all = readFileSync28(HISTORY_FILE, "utf8").trim().split("\n");
41575
41905
  if (all.length > MAX_HISTORY_LINES) {
41576
- 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");
41577
41907
  }
41578
41908
  }
41579
41909
  } catch {
@@ -42433,8 +42763,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
42433
42763
  return true;
42434
42764
  },
42435
42765
  destroyProject() {
42436
- const oaPath = join48(repoRoot, OA_DIR);
42437
- if (existsSync37(oaPath)) {
42766
+ const oaPath = join49(repoRoot, OA_DIR);
42767
+ if (existsSync38(oaPath)) {
42438
42768
  try {
42439
42769
  rmSync2(oaPath, { recursive: true, force: true });
42440
42770
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -42765,13 +43095,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
42765
43095
  }
42766
43096
  }
42767
43097
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
42768
- const isImage = isImagePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
42769
- 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));
42770
43100
  if (activeTask) {
42771
43101
  if (isImage) {
42772
43102
  try {
42773
43103
  const imgPath = resolve28(repoRoot, cleanPath);
42774
- const imgBuffer = readFileSync27(imgPath);
43104
+ const imgBuffer = readFileSync28(imgPath);
42775
43105
  const base64 = imgBuffer.toString("base64");
42776
43106
  const ext = extname9(cleanPath).toLowerCase();
42777
43107
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -43285,7 +43615,7 @@ import { glob } from "glob";
43285
43615
  import ignore from "ignore";
43286
43616
  import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
43287
43617
  import { createHash as createHash4 } from "node:crypto";
43288
- 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";
43289
43619
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
43290
43620
  var init_codebase_indexer = __esm({
43291
43621
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -43329,7 +43659,7 @@ var init_codebase_indexer = __esm({
43329
43659
  const ig = ignore.default();
43330
43660
  if (this.config.respectGitignore) {
43331
43661
  try {
43332
- const gitignoreContent = await readFile16(join49(this.config.rootDir, ".gitignore"), "utf-8");
43662
+ const gitignoreContent = await readFile16(join50(this.config.rootDir, ".gitignore"), "utf-8");
43333
43663
  ig.add(gitignoreContent);
43334
43664
  } catch {
43335
43665
  }
@@ -43344,7 +43674,7 @@ var init_codebase_indexer = __esm({
43344
43674
  for (const relativePath of files) {
43345
43675
  if (ig.ignores(relativePath))
43346
43676
  continue;
43347
- const fullPath = join49(this.config.rootDir, relativePath);
43677
+ const fullPath = join50(this.config.rootDir, relativePath);
43348
43678
  try {
43349
43679
  const fileStat = await stat4(fullPath);
43350
43680
  if (fileStat.size > this.config.maxFileSize)
@@ -43390,7 +43720,7 @@ var init_codebase_indexer = __esm({
43390
43720
  if (!child) {
43391
43721
  child = {
43392
43722
  name: part,
43393
- path: join49(current.path, part),
43723
+ path: join50(current.path, part),
43394
43724
  type: "directory",
43395
43725
  children: []
43396
43726
  };
@@ -43473,13 +43803,13 @@ __export(index_repo_exports, {
43473
43803
  indexRepoCommand: () => indexRepoCommand
43474
43804
  });
43475
43805
  import { resolve as resolve29 } from "node:path";
43476
- import { existsSync as existsSync38, statSync as statSync11 } from "node:fs";
43806
+ import { existsSync as existsSync39, statSync as statSync11 } from "node:fs";
43477
43807
  import { cwd as cwd2 } from "node:process";
43478
43808
  async function indexRepoCommand(opts, _config) {
43479
43809
  const repoRoot = resolve29(opts.repoPath ?? cwd2());
43480
43810
  printHeader("Index Repository");
43481
43811
  printInfo(`Indexing: ${repoRoot}`);
43482
- if (!existsSync38(repoRoot)) {
43812
+ if (!existsSync39(repoRoot)) {
43483
43813
  printError(`Path does not exist: ${repoRoot}`);
43484
43814
  process.exit(1);
43485
43815
  }
@@ -43731,7 +44061,7 @@ var config_exports = {};
43731
44061
  __export(config_exports, {
43732
44062
  configCommand: () => configCommand
43733
44063
  });
43734
- import { join as join50, resolve as resolve30 } from "node:path";
44064
+ import { join as join51, resolve as resolve30 } from "node:path";
43735
44065
  import { homedir as homedir14 } from "node:os";
43736
44066
  import { cwd as cwd3 } from "node:process";
43737
44067
  function redactIfSensitive(key, value) {
@@ -43790,7 +44120,7 @@ function handleShow(opts, config) {
43790
44120
  }
43791
44121
  }
43792
44122
  printSection("Config File");
43793
- printInfo(`~/.open-agents/config.json (${join50(homedir14(), ".open-agents", "config.json")})`);
44123
+ printInfo(`~/.open-agents/config.json (${join51(homedir14(), ".open-agents", "config.json")})`);
43794
44124
  printSection("Priority Chain");
43795
44125
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
43796
44126
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -43829,7 +44159,7 @@ function handleSet(opts, _config) {
43829
44159
  const coerced = coerceForSettings(key, value);
43830
44160
  saveProjectSettings(repoRoot, { [key]: coerced });
43831
44161
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
43832
- printInfo(`Saved to ${join50(repoRoot, ".oa", "settings.json")}`);
44162
+ printInfo(`Saved to ${join51(repoRoot, ".oa", "settings.json")}`);
43833
44163
  printInfo("This override applies only when running in this workspace.");
43834
44164
  } catch (err) {
43835
44165
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -44048,8 +44378,8 @@ __export(eval_exports, {
44048
44378
  evalCommand: () => evalCommand
44049
44379
  });
44050
44380
  import { tmpdir as tmpdir7 } from "node:os";
44051
- import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "node:fs";
44052
- 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";
44053
44383
  async function evalCommand(opts, config) {
44054
44384
  const suiteName = opts.suite ?? "basic";
44055
44385
  const suite = SUITES[suiteName];
@@ -44174,9 +44504,9 @@ async function evalCommand(opts, config) {
44174
44504
  process.exit(failed > 0 ? 1 : 0);
44175
44505
  }
44176
44506
  function createTempEvalRepo() {
44177
- const dir = join51(tmpdir7(), `open-agents-eval-${Date.now()}`);
44178
- mkdirSync17(dir, { recursive: true });
44179
- 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");
44180
44510
  return dir;
44181
44511
  }
44182
44512
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -44236,7 +44566,7 @@ init_updater();
44236
44566
  import { parseArgs as nodeParseArgs2 } from "node:util";
44237
44567
  import { createRequire as createRequire3 } from "node:module";
44238
44568
  import { fileURLToPath as fileURLToPath13 } from "node:url";
44239
- import { dirname as dirname17, join as join52 } from "node:path";
44569
+ import { dirname as dirname18, join as join53 } from "node:path";
44240
44570
 
44241
44571
  // packages/cli/dist/cli.js
44242
44572
  import { createInterface } from "node:readline";
@@ -44343,7 +44673,7 @@ init_output();
44343
44673
  function getVersion4() {
44344
44674
  try {
44345
44675
  const require2 = createRequire3(import.meta.url);
44346
- const pkgPath = join52(dirname17(fileURLToPath13(import.meta.url)), "..", "package.json");
44676
+ const pkgPath = join53(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
44347
44677
  const pkg = require2(pkgPath);
44348
44678
  return pkg.version;
44349
44679
  } catch {