open-agents-ai 0.30.6 → 0.30.8
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 +728 -301
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1284,7 +1284,7 @@ ${stdinInput ?? ""}`);
|
|
|
1284
1284
|
}
|
|
1285
1285
|
runCommand(command, timeout, stdinInput) {
|
|
1286
1286
|
const start = performance.now();
|
|
1287
|
-
return new Promise((
|
|
1287
|
+
return new Promise((resolve21) => {
|
|
1288
1288
|
const child = spawn("bash", ["-c", command], {
|
|
1289
1289
|
cwd: this.workingDir,
|
|
1290
1290
|
env: {
|
|
@@ -1312,7 +1312,7 @@ ${stdinInput ?? ""}`);
|
|
|
1312
1312
|
clearTimeout(timer);
|
|
1313
1313
|
if (exitFlushTimer)
|
|
1314
1314
|
clearTimeout(exitFlushTimer);
|
|
1315
|
-
|
|
1315
|
+
resolve21(result);
|
|
1316
1316
|
};
|
|
1317
1317
|
const timer = setTimeout(() => {
|
|
1318
1318
|
killed = true;
|
|
@@ -3967,21 +3967,29 @@ function detectPackageManager() {
|
|
|
3967
3967
|
_detectedPkgManager = null;
|
|
3968
3968
|
return _detectedPkgManager;
|
|
3969
3969
|
}
|
|
3970
|
+
if (plat === "win32") {
|
|
3971
|
+
if (hasCommand("choco"))
|
|
3972
|
+
_detectedPkgManager = "choco";
|
|
3973
|
+
else
|
|
3974
|
+
_detectedPkgManager = null;
|
|
3975
|
+
return _detectedPkgManager;
|
|
3976
|
+
}
|
|
3970
3977
|
_detectedPkgManager = null;
|
|
3971
3978
|
return null;
|
|
3972
3979
|
}
|
|
3973
3980
|
function hasCommand(cmd) {
|
|
3974
3981
|
try {
|
|
3975
|
-
|
|
3982
|
+
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
3983
|
+
execSync6(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
3976
3984
|
return true;
|
|
3977
3985
|
} catch {
|
|
3978
3986
|
return false;
|
|
3979
3987
|
}
|
|
3980
3988
|
}
|
|
3981
3989
|
function runInstall(installCmd) {
|
|
3982
|
-
const
|
|
3990
|
+
const plat = process.platform;
|
|
3983
3991
|
let cmd = installCmd;
|
|
3984
|
-
if (
|
|
3992
|
+
if (plat === "linux") {
|
|
3985
3993
|
if (_sudoPassword) {
|
|
3986
3994
|
cmd = `echo ${JSON.stringify(_sudoPassword)} | sudo -S ${installCmd}`;
|
|
3987
3995
|
} else {
|
|
@@ -4048,6 +4056,9 @@ function ensureCommand(command) {
|
|
|
4048
4056
|
case "brew":
|
|
4049
4057
|
installCmd = `brew install ${pkg}`;
|
|
4050
4058
|
break;
|
|
4059
|
+
case "choco":
|
|
4060
|
+
installCmd = `choco install -y ${pkg}`;
|
|
4061
|
+
break;
|
|
4051
4062
|
}
|
|
4052
4063
|
try {
|
|
4053
4064
|
runInstall(installCmd);
|
|
@@ -4099,9 +4110,27 @@ var init_system_deps = __esm({
|
|
|
4099
4110
|
},
|
|
4100
4111
|
{
|
|
4101
4112
|
command: "identify",
|
|
4102
|
-
packages: { apt: "imagemagick", dnf: "ImageMagick", pacman: "imagemagick", brew: "imagemagick" },
|
|
4113
|
+
packages: { apt: "imagemagick", dnf: "ImageMagick", pacman: "imagemagick", brew: "imagemagick", choco: "imagemagick" },
|
|
4103
4114
|
description: "Image metadata and conversion (ImageMagick)",
|
|
4104
4115
|
group: "image"
|
|
4116
|
+
},
|
|
4117
|
+
{
|
|
4118
|
+
command: "ocrmypdf",
|
|
4119
|
+
packages: { apt: "ocrmypdf", dnf: "ocrmypdf", pacman: "ocrmypdf", brew: "ocrmypdf", choco: "ocrmypdf" },
|
|
4120
|
+
description: "OCR-based PDF text layer injection",
|
|
4121
|
+
group: "pdf"
|
|
4122
|
+
},
|
|
4123
|
+
{
|
|
4124
|
+
command: "pdftotext",
|
|
4125
|
+
packages: { apt: "poppler-utils", dnf: "poppler-utils", pacman: "poppler", brew: "poppler", choco: "poppler" },
|
|
4126
|
+
description: "PDF text extraction (Poppler)",
|
|
4127
|
+
group: "pdf"
|
|
4128
|
+
},
|
|
4129
|
+
{
|
|
4130
|
+
command: "gs",
|
|
4131
|
+
packages: { apt: "ghostscript", dnf: "ghostscript", pacman: "ghostscript", brew: "ghostscript", choco: "ghostscript" },
|
|
4132
|
+
description: "PostScript/PDF rendering (Ghostscript, required by ocrmypdf)",
|
|
4133
|
+
group: "pdf"
|
|
4105
4134
|
}
|
|
4106
4135
|
];
|
|
4107
4136
|
_cache = /* @__PURE__ */ new Map();
|
|
@@ -4534,8 +4563,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
|
|
|
4534
4563
|
const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
|
|
4535
4564
|
const filePath = join11(dir, `${name}.json`);
|
|
4536
4565
|
if (existsSync8(filePath)) {
|
|
4537
|
-
const { unlinkSync:
|
|
4538
|
-
|
|
4566
|
+
const { unlinkSync: unlinkSync5 } = __require("node:fs");
|
|
4567
|
+
unlinkSync5(filePath);
|
|
4539
4568
|
return true;
|
|
4540
4569
|
}
|
|
4541
4570
|
return false;
|
|
@@ -4653,7 +4682,7 @@ var init_custom_tool = __esm({
|
|
|
4653
4682
|
}
|
|
4654
4683
|
/** Execute a single shell command and return output */
|
|
4655
4684
|
runCommand(command) {
|
|
4656
|
-
return new Promise((
|
|
4685
|
+
return new Promise((resolve21) => {
|
|
4657
4686
|
const child = spawn3("bash", ["-c", command], {
|
|
4658
4687
|
cwd: this.workingDir,
|
|
4659
4688
|
env: { ...process.env, CI: "true", NO_COLOR: "1" },
|
|
@@ -4678,11 +4707,11 @@ var init_custom_tool = __esm({
|
|
|
4678
4707
|
child.kill("SIGTERM");
|
|
4679
4708
|
} catch {
|
|
4680
4709
|
}
|
|
4681
|
-
|
|
4710
|
+
resolve21({ success: false, output: stdout, error: "Command timed out after 60s" });
|
|
4682
4711
|
}, 6e4);
|
|
4683
4712
|
child.on("close", (code) => {
|
|
4684
4713
|
clearTimeout(timer);
|
|
4685
|
-
|
|
4714
|
+
resolve21({
|
|
4686
4715
|
success: code === 0,
|
|
4687
4716
|
output: stdout + (stderr && code === 0 ? `
|
|
4688
4717
|
STDERR:
|
|
@@ -4692,7 +4721,7 @@ ${stderr}` : ""),
|
|
|
4692
4721
|
});
|
|
4693
4722
|
child.on("error", (err) => {
|
|
4694
4723
|
clearTimeout(timer);
|
|
4695
|
-
|
|
4724
|
+
resolve21({ success: false, output: stdout, error: err.message });
|
|
4696
4725
|
});
|
|
4697
4726
|
});
|
|
4698
4727
|
}
|
|
@@ -5874,7 +5903,7 @@ import { writeFile as writeFile7, mkdtemp, rm, readdir, stat } from "node:fs/pro
|
|
|
5874
5903
|
import { join as join14 } from "node:path";
|
|
5875
5904
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
5876
5905
|
function runProcess(cmd, args, options) {
|
|
5877
|
-
return new Promise((
|
|
5906
|
+
return new Promise((resolve21) => {
|
|
5878
5907
|
const proc = spawn5(cmd, args, {
|
|
5879
5908
|
cwd: options.cwd,
|
|
5880
5909
|
timeout: options.timeout,
|
|
@@ -5904,7 +5933,7 @@ function runProcess(cmd, args, options) {
|
|
|
5904
5933
|
}
|
|
5905
5934
|
});
|
|
5906
5935
|
proc.on("error", (err) => {
|
|
5907
|
-
|
|
5936
|
+
resolve21({
|
|
5908
5937
|
stdout,
|
|
5909
5938
|
stderr: stderr || err.message,
|
|
5910
5939
|
exitCode: 1,
|
|
@@ -5916,7 +5945,7 @@ function runProcess(cmd, args, options) {
|
|
|
5916
5945
|
if (signal === "SIGTERM" || signal === "SIGKILL") {
|
|
5917
5946
|
timedOut = true;
|
|
5918
5947
|
}
|
|
5919
|
-
|
|
5948
|
+
resolve21({
|
|
5920
5949
|
stdout,
|
|
5921
5950
|
stderr,
|
|
5922
5951
|
exitCode: code ?? (timedOut ? 124 : 1),
|
|
@@ -7333,6 +7362,314 @@ Screen: ${dims.width}x${dims.height}`);
|
|
|
7333
7362
|
}
|
|
7334
7363
|
});
|
|
7335
7364
|
|
|
7365
|
+
// packages/execution/dist/tools/ocr-pdf.js
|
|
7366
|
+
import { existsSync as existsSync13, statSync as statSync6 } from "node:fs";
|
|
7367
|
+
import { resolve as resolve16, basename as basename5 } from "node:path";
|
|
7368
|
+
import { execSync as execSync12 } from "node:child_process";
|
|
7369
|
+
var OcrPdfTool;
|
|
7370
|
+
var init_ocr_pdf = __esm({
|
|
7371
|
+
"packages/execution/dist/tools/ocr-pdf.js"() {
|
|
7372
|
+
"use strict";
|
|
7373
|
+
init_system_deps();
|
|
7374
|
+
OcrPdfTool = class {
|
|
7375
|
+
workingDir;
|
|
7376
|
+
name = "ocr_pdf";
|
|
7377
|
+
description = "Add a searchable text layer to a scanned or image-based PDF using OCR. The output PDF looks identical but contains selectable/searchable text. Uses ocrmypdf with Tesseract. Auto-installs dependencies if missing.";
|
|
7378
|
+
parameters = {
|
|
7379
|
+
type: "object",
|
|
7380
|
+
properties: {
|
|
7381
|
+
input: {
|
|
7382
|
+
type: "string",
|
|
7383
|
+
description: "Path to the input PDF file"
|
|
7384
|
+
},
|
|
7385
|
+
output: {
|
|
7386
|
+
type: "string",
|
|
7387
|
+
description: "Path for the output PDF (default: overwrites input with --output-type pdfa)"
|
|
7388
|
+
},
|
|
7389
|
+
language: {
|
|
7390
|
+
type: "string",
|
|
7391
|
+
description: "OCR language(s) (default: eng). Use '+' for multiple: 'eng+fra+deu'"
|
|
7392
|
+
},
|
|
7393
|
+
deskew: {
|
|
7394
|
+
type: "boolean",
|
|
7395
|
+
description: "Deskew pages before OCR (default: true)"
|
|
7396
|
+
},
|
|
7397
|
+
force_ocr: {
|
|
7398
|
+
type: "boolean",
|
|
7399
|
+
description: "Force OCR even if text layer exists (default: false)"
|
|
7400
|
+
}
|
|
7401
|
+
},
|
|
7402
|
+
required: ["input"]
|
|
7403
|
+
};
|
|
7404
|
+
constructor(workingDir) {
|
|
7405
|
+
this.workingDir = workingDir;
|
|
7406
|
+
}
|
|
7407
|
+
async execute(args) {
|
|
7408
|
+
const start = performance.now();
|
|
7409
|
+
const rawInput = args["input"];
|
|
7410
|
+
const rawOutput = args["output"];
|
|
7411
|
+
const language = args["language"] ?? "eng";
|
|
7412
|
+
const deskew = args["deskew"] !== false;
|
|
7413
|
+
const forceOcr = args["force_ocr"] === true;
|
|
7414
|
+
if (!rawInput) {
|
|
7415
|
+
return { success: false, output: "", error: "input path is required", durationMs: 0 };
|
|
7416
|
+
}
|
|
7417
|
+
const inputPath = resolve16(this.workingDir, rawInput);
|
|
7418
|
+
if (!existsSync13(inputPath)) {
|
|
7419
|
+
return { success: false, output: "", error: `File not found: ${rawInput}`, durationMs: performance.now() - start };
|
|
7420
|
+
}
|
|
7421
|
+
const stat5 = statSync6(inputPath);
|
|
7422
|
+
if (stat5.size > 500 * 1024 * 1024) {
|
|
7423
|
+
return { success: false, output: "", error: `PDF too large: ${(stat5.size / 1024 / 1024).toFixed(0)}MB (max 500MB)`, durationMs: performance.now() - start };
|
|
7424
|
+
}
|
|
7425
|
+
const deps = ["ocrmypdf", "tesseract", "gs"];
|
|
7426
|
+
const missing = [];
|
|
7427
|
+
for (const dep of deps) {
|
|
7428
|
+
const result = ensureCommand(dep);
|
|
7429
|
+
if (!result.available) {
|
|
7430
|
+
missing.push(`${dep}${result.error ? `: ${result.error}` : ""}`);
|
|
7431
|
+
}
|
|
7432
|
+
}
|
|
7433
|
+
if (missing.length > 0) {
|
|
7434
|
+
return {
|
|
7435
|
+
success: false,
|
|
7436
|
+
output: "",
|
|
7437
|
+
error: `Missing dependencies: ${missing.join("; ")}`,
|
|
7438
|
+
durationMs: performance.now() - start
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
const outputPath = rawOutput ? resolve16(this.workingDir, rawOutput) : inputPath;
|
|
7442
|
+
const cmdParts = ["ocrmypdf"];
|
|
7443
|
+
cmdParts.push("-l", language);
|
|
7444
|
+
if (deskew)
|
|
7445
|
+
cmdParts.push("--deskew");
|
|
7446
|
+
if (forceOcr)
|
|
7447
|
+
cmdParts.push("--force-ocr");
|
|
7448
|
+
cmdParts.push("--skip-text");
|
|
7449
|
+
if (forceOcr) {
|
|
7450
|
+
cmdParts.splice(cmdParts.indexOf("--skip-text"), 1);
|
|
7451
|
+
}
|
|
7452
|
+
cmdParts.push(JSON.stringify(inputPath));
|
|
7453
|
+
cmdParts.push(JSON.stringify(outputPath));
|
|
7454
|
+
try {
|
|
7455
|
+
const stdout = execSync12(cmdParts.join(" "), {
|
|
7456
|
+
encoding: "utf8",
|
|
7457
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
7458
|
+
timeout: 6e5,
|
|
7459
|
+
// 10 min for large PDFs
|
|
7460
|
+
cwd: this.workingDir
|
|
7461
|
+
});
|
|
7462
|
+
const outputStat = statSync6(outputPath);
|
|
7463
|
+
const sizeMB = (outputStat.size / 1024 / 1024).toFixed(1);
|
|
7464
|
+
return {
|
|
7465
|
+
success: true,
|
|
7466
|
+
output: `OCR completed for ${basename5(inputPath)}
|
|
7467
|
+
Output: ${outputPath === inputPath ? "(in-place)" : outputPath}
|
|
7468
|
+
Size: ${sizeMB}MB
|
|
7469
|
+
Language: ${language}
|
|
7470
|
+
` + (stdout.trim() ? `Details: ${stdout.trim()}` : "PDF now has a searchable text layer."),
|
|
7471
|
+
durationMs: performance.now() - start
|
|
7472
|
+
};
|
|
7473
|
+
} catch (err) {
|
|
7474
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7475
|
+
const stderr = err?.stderr?.toString?.() ?? "";
|
|
7476
|
+
return {
|
|
7477
|
+
success: false,
|
|
7478
|
+
output: "",
|
|
7479
|
+
error: `ocrmypdf failed: ${stderr || msg}`.slice(0, 500),
|
|
7480
|
+
durationMs: performance.now() - start
|
|
7481
|
+
};
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
};
|
|
7485
|
+
}
|
|
7486
|
+
});
|
|
7487
|
+
|
|
7488
|
+
// packages/execution/dist/tools/pdf-to-text.js
|
|
7489
|
+
import { existsSync as existsSync14, statSync as statSync7, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "node:fs";
|
|
7490
|
+
import { resolve as resolve17, basename as basename6, join as join17 } from "node:path";
|
|
7491
|
+
import { execSync as execSync13 } from "node:child_process";
|
|
7492
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
7493
|
+
var PdfToTextTool;
|
|
7494
|
+
var init_pdf_to_text = __esm({
|
|
7495
|
+
"packages/execution/dist/tools/pdf-to-text.js"() {
|
|
7496
|
+
"use strict";
|
|
7497
|
+
init_system_deps();
|
|
7498
|
+
PdfToTextTool = class {
|
|
7499
|
+
workingDir;
|
|
7500
|
+
name = "pdf_to_text";
|
|
7501
|
+
description = "Extract text content from a PDF file. Uses pdftotext (Poppler) for native PDFs. For scanned/image PDFs with no text layer, can optionally OCR first via ocrmypdf. Auto-installs dependencies if missing.";
|
|
7502
|
+
parameters = {
|
|
7503
|
+
type: "object",
|
|
7504
|
+
properties: {
|
|
7505
|
+
path: {
|
|
7506
|
+
type: "string",
|
|
7507
|
+
description: "Path to the PDF file"
|
|
7508
|
+
},
|
|
7509
|
+
pages: {
|
|
7510
|
+
type: "string",
|
|
7511
|
+
description: "Page range to extract: 'first' (page 1), 'N' (single page), 'N-M' (range). Default: all pages."
|
|
7512
|
+
},
|
|
7513
|
+
layout: {
|
|
7514
|
+
type: "boolean",
|
|
7515
|
+
description: "Preserve original layout/formatting (default: false \u2014 flows text naturally)"
|
|
7516
|
+
},
|
|
7517
|
+
ocr_if_empty: {
|
|
7518
|
+
type: "boolean",
|
|
7519
|
+
description: "If pdftotext returns no text, try OCR via ocrmypdf first (default: true)"
|
|
7520
|
+
},
|
|
7521
|
+
language: {
|
|
7522
|
+
type: "string",
|
|
7523
|
+
description: "OCR language if OCR fallback is used (default: eng)"
|
|
7524
|
+
}
|
|
7525
|
+
},
|
|
7526
|
+
required: ["path"]
|
|
7527
|
+
};
|
|
7528
|
+
constructor(workingDir) {
|
|
7529
|
+
this.workingDir = workingDir;
|
|
7530
|
+
}
|
|
7531
|
+
async execute(args) {
|
|
7532
|
+
const start = performance.now();
|
|
7533
|
+
const rawPath = args["path"];
|
|
7534
|
+
const pages = args["pages"];
|
|
7535
|
+
const layout = args["layout"] === true;
|
|
7536
|
+
const ocrIfEmpty = args["ocr_if_empty"] !== false;
|
|
7537
|
+
const language = args["language"] ?? "eng";
|
|
7538
|
+
if (!rawPath) {
|
|
7539
|
+
return { success: false, output: "", error: "path is required", durationMs: 0 };
|
|
7540
|
+
}
|
|
7541
|
+
const fullPath = resolve17(this.workingDir, rawPath);
|
|
7542
|
+
if (!existsSync14(fullPath)) {
|
|
7543
|
+
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
|
|
7544
|
+
}
|
|
7545
|
+
const fileStat = statSync7(fullPath);
|
|
7546
|
+
if (fileStat.size > 500 * 1024 * 1024) {
|
|
7547
|
+
return { success: false, output: "", error: `PDF too large: ${(fileStat.size / 1024 / 1024).toFixed(0)}MB (max 500MB)`, durationMs: performance.now() - start };
|
|
7548
|
+
}
|
|
7549
|
+
const pdftotextCheck = ensureCommand("pdftotext");
|
|
7550
|
+
if (!pdftotextCheck.available) {
|
|
7551
|
+
return {
|
|
7552
|
+
success: false,
|
|
7553
|
+
output: "",
|
|
7554
|
+
error: `pdftotext not available: ${pdftotextCheck.error ?? "auto-install failed"}`,
|
|
7555
|
+
durationMs: performance.now() - start
|
|
7556
|
+
};
|
|
7557
|
+
}
|
|
7558
|
+
const cmdParts = ["pdftotext"];
|
|
7559
|
+
if (layout)
|
|
7560
|
+
cmdParts.push("-layout");
|
|
7561
|
+
let firstPage;
|
|
7562
|
+
let lastPage;
|
|
7563
|
+
if (pages) {
|
|
7564
|
+
if (pages === "first") {
|
|
7565
|
+
firstPage = 1;
|
|
7566
|
+
lastPage = 1;
|
|
7567
|
+
} else if (pages.includes("-")) {
|
|
7568
|
+
const [a, b] = pages.split("-").map(Number);
|
|
7569
|
+
if (a && b) {
|
|
7570
|
+
firstPage = a;
|
|
7571
|
+
lastPage = b;
|
|
7572
|
+
}
|
|
7573
|
+
} else {
|
|
7574
|
+
const n = Number(pages);
|
|
7575
|
+
if (n) {
|
|
7576
|
+
firstPage = n;
|
|
7577
|
+
lastPage = n;
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
}
|
|
7581
|
+
if (firstPage)
|
|
7582
|
+
cmdParts.push("-f", String(firstPage));
|
|
7583
|
+
if (lastPage)
|
|
7584
|
+
cmdParts.push("-l", String(lastPage));
|
|
7585
|
+
cmdParts.push(JSON.stringify(fullPath), "-");
|
|
7586
|
+
try {
|
|
7587
|
+
let text = execSync13(cmdParts.join(" "), {
|
|
7588
|
+
encoding: "utf8",
|
|
7589
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
7590
|
+
timeout: 12e4
|
|
7591
|
+
}).trim();
|
|
7592
|
+
if (!text && ocrIfEmpty) {
|
|
7593
|
+
const ocrText = await this.ocrFallback(fullPath, language, firstPage, lastPage);
|
|
7594
|
+
if (ocrText) {
|
|
7595
|
+
text = ocrText;
|
|
7596
|
+
const lineCount2 = text.split("\n").length;
|
|
7597
|
+
const pageInfo2 = pages ? ` (pages: ${pages})` : "";
|
|
7598
|
+
return {
|
|
7599
|
+
success: true,
|
|
7600
|
+
output: `Extracted ${lineCount2} lines from ${basename6(fullPath)}${pageInfo2} (via OCR):
|
|
7601
|
+
|
|
7602
|
+
${text}`,
|
|
7603
|
+
durationMs: performance.now() - start
|
|
7604
|
+
};
|
|
7605
|
+
}
|
|
7606
|
+
return {
|
|
7607
|
+
success: true,
|
|
7608
|
+
output: `No text found in ${basename6(fullPath)} \u2014 appears to be a scanned/image PDF with no extractable text. OCR also returned no results.`,
|
|
7609
|
+
durationMs: performance.now() - start
|
|
7610
|
+
};
|
|
7611
|
+
}
|
|
7612
|
+
if (!text) {
|
|
7613
|
+
return {
|
|
7614
|
+
success: true,
|
|
7615
|
+
output: `No text found in ${basename6(fullPath)} \u2014 may be a scanned/image PDF. Use ocr_pdf tool to add a text layer first.`,
|
|
7616
|
+
durationMs: performance.now() - start
|
|
7617
|
+
};
|
|
7618
|
+
}
|
|
7619
|
+
const lineCount = text.split("\n").length;
|
|
7620
|
+
const pageInfo = pages ? ` (pages: ${pages})` : "";
|
|
7621
|
+
return {
|
|
7622
|
+
success: true,
|
|
7623
|
+
output: `Extracted ${lineCount} lines from ${basename6(fullPath)}${pageInfo}:
|
|
7624
|
+
|
|
7625
|
+
${text}`,
|
|
7626
|
+
durationMs: performance.now() - start
|
|
7627
|
+
};
|
|
7628
|
+
} catch (err) {
|
|
7629
|
+
return {
|
|
7630
|
+
success: false,
|
|
7631
|
+
output: "",
|
|
7632
|
+
error: `pdftotext failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
7633
|
+
durationMs: performance.now() - start
|
|
7634
|
+
};
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
async ocrFallback(inputPath, language, firstPage, lastPage) {
|
|
7638
|
+
const ocrCheck = ensureCommand("ocrmypdf");
|
|
7639
|
+
const tesCheck = ensureCommand("tesseract");
|
|
7640
|
+
const gsCheck = ensureCommand("gs");
|
|
7641
|
+
if (!ocrCheck.available || !tesCheck.available || !gsCheck.available) {
|
|
7642
|
+
return null;
|
|
7643
|
+
}
|
|
7644
|
+
const tmpPdf = join17(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
|
|
7645
|
+
try {
|
|
7646
|
+
const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
|
|
7647
|
+
execSync13(ocrCmd, { stdio: "pipe", timeout: 6e5 });
|
|
7648
|
+
const textCmdParts = ["pdftotext"];
|
|
7649
|
+
if (firstPage)
|
|
7650
|
+
textCmdParts.push("-f", String(firstPage));
|
|
7651
|
+
if (lastPage)
|
|
7652
|
+
textCmdParts.push("-l", String(lastPage));
|
|
7653
|
+
textCmdParts.push(JSON.stringify(tmpPdf), "-");
|
|
7654
|
+
const text = execSync13(textCmdParts.join(" "), {
|
|
7655
|
+
encoding: "utf8",
|
|
7656
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
7657
|
+
timeout: 12e4
|
|
7658
|
+
}).trim();
|
|
7659
|
+
return text || null;
|
|
7660
|
+
} catch {
|
|
7661
|
+
return null;
|
|
7662
|
+
} finally {
|
|
7663
|
+
try {
|
|
7664
|
+
unlinkSync2(tmpPdf);
|
|
7665
|
+
} catch {
|
|
7666
|
+
}
|
|
7667
|
+
}
|
|
7668
|
+
}
|
|
7669
|
+
};
|
|
7670
|
+
}
|
|
7671
|
+
});
|
|
7672
|
+
|
|
7336
7673
|
// packages/execution/dist/shellRunner.js
|
|
7337
7674
|
var init_shellRunner = __esm({
|
|
7338
7675
|
"packages/execution/dist/shellRunner.js"() {
|
|
@@ -7442,6 +7779,8 @@ var init_dist2 = __esm({
|
|
|
7442
7779
|
init_structured_read();
|
|
7443
7780
|
init_vision();
|
|
7444
7781
|
init_desktop_click();
|
|
7782
|
+
init_ocr_pdf();
|
|
7783
|
+
init_pdf_to_text();
|
|
7445
7784
|
init_system_deps();
|
|
7446
7785
|
init_shellRunner();
|
|
7447
7786
|
init_gitWorktree();
|
|
@@ -8574,7 +8913,7 @@ var init_code_retriever = __esm({
|
|
|
8574
8913
|
import { execFile as execFile4 } from "node:child_process";
|
|
8575
8914
|
import { promisify as promisify4 } from "node:util";
|
|
8576
8915
|
import { readFile as readFile8, readdir as readdir2, stat as stat3 } from "node:fs/promises";
|
|
8577
|
-
import { join as
|
|
8916
|
+
import { join as join18, extname as extname7 } from "node:path";
|
|
8578
8917
|
async function searchByPath(pathPattern, options) {
|
|
8579
8918
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
8580
8919
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -8716,7 +9055,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
8716
9055
|
continue;
|
|
8717
9056
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
8718
9057
|
continue;
|
|
8719
|
-
const absPath =
|
|
9058
|
+
const absPath = join18(dir, entry.name);
|
|
8720
9059
|
if (entry.isDirectory()) {
|
|
8721
9060
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
8722
9061
|
} else if (entry.isFile()) {
|
|
@@ -8891,7 +9230,7 @@ var init_graphExpand = __esm({
|
|
|
8891
9230
|
|
|
8892
9231
|
// packages/retrieval/dist/snippetPacker.js
|
|
8893
9232
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
8894
|
-
import { join as
|
|
9233
|
+
import { join as join19 } from "node:path";
|
|
8895
9234
|
async function packSnippets(requests, opts = {}) {
|
|
8896
9235
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
8897
9236
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -8917,7 +9256,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
8917
9256
|
return { packed, dropped, totalTokens };
|
|
8918
9257
|
}
|
|
8919
9258
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
8920
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
9259
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join19(repoRoot, req.filePath);
|
|
8921
9260
|
let content;
|
|
8922
9261
|
try {
|
|
8923
9262
|
content = await readFile9(absPath, "utf-8");
|
|
@@ -10430,8 +10769,8 @@ Rules:
|
|
|
10430
10769
|
async waitIfPaused() {
|
|
10431
10770
|
if (!this._paused)
|
|
10432
10771
|
return true;
|
|
10433
|
-
await new Promise((
|
|
10434
|
-
this._pauseResolve =
|
|
10772
|
+
await new Promise((resolve21) => {
|
|
10773
|
+
this._pauseResolve = resolve21;
|
|
10435
10774
|
});
|
|
10436
10775
|
return !this.aborted;
|
|
10437
10776
|
}
|
|
@@ -10941,14 +11280,14 @@ ${result.output}`;
|
|
|
10941
11280
|
waitForSudoPassword(timeoutMs = 12e4) {
|
|
10942
11281
|
if (this._sudoPassword)
|
|
10943
11282
|
return Promise.resolve(this._sudoPassword);
|
|
10944
|
-
return new Promise((
|
|
11283
|
+
return new Promise((resolve21) => {
|
|
10945
11284
|
const timer = setTimeout(() => {
|
|
10946
11285
|
this._sudoResolve = null;
|
|
10947
|
-
|
|
11286
|
+
resolve21(null);
|
|
10948
11287
|
}, timeoutMs);
|
|
10949
11288
|
this._sudoResolve = (pw) => {
|
|
10950
11289
|
clearTimeout(timer);
|
|
10951
|
-
|
|
11290
|
+
resolve21(pw);
|
|
10952
11291
|
};
|
|
10953
11292
|
});
|
|
10954
11293
|
}
|
|
@@ -12104,9 +12443,9 @@ var init_dist5 = __esm({
|
|
|
12104
12443
|
});
|
|
12105
12444
|
|
|
12106
12445
|
// packages/cli/dist/tui/listen.js
|
|
12107
|
-
import { spawn as spawn7, execSync as
|
|
12108
|
-
import { existsSync as
|
|
12109
|
-
import { join as
|
|
12446
|
+
import { spawn as spawn7, execSync as execSync14 } from "node:child_process";
|
|
12447
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
|
|
12448
|
+
import { join as join20, dirname as dirname6 } from "node:path";
|
|
12110
12449
|
import { homedir as homedir6 } from "node:os";
|
|
12111
12450
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
12112
12451
|
import { EventEmitter } from "node:events";
|
|
@@ -12126,7 +12465,7 @@ function findMicCaptureCommand() {
|
|
|
12126
12465
|
const platform4 = process.platform;
|
|
12127
12466
|
if (platform4 === "linux") {
|
|
12128
12467
|
try {
|
|
12129
|
-
|
|
12468
|
+
execSync14("which arecord", { stdio: "pipe" });
|
|
12130
12469
|
return {
|
|
12131
12470
|
cmd: "arecord",
|
|
12132
12471
|
args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
|
|
@@ -12136,7 +12475,7 @@ function findMicCaptureCommand() {
|
|
|
12136
12475
|
}
|
|
12137
12476
|
if (platform4 === "darwin") {
|
|
12138
12477
|
try {
|
|
12139
|
-
|
|
12478
|
+
execSync14("which sox", { stdio: "pipe" });
|
|
12140
12479
|
return {
|
|
12141
12480
|
cmd: "sox",
|
|
12142
12481
|
args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
|
|
@@ -12145,7 +12484,7 @@ function findMicCaptureCommand() {
|
|
|
12145
12484
|
}
|
|
12146
12485
|
}
|
|
12147
12486
|
try {
|
|
12148
|
-
|
|
12487
|
+
execSync14("which ffmpeg", { stdio: "pipe" });
|
|
12149
12488
|
if (platform4 === "linux") {
|
|
12150
12489
|
return {
|
|
12151
12490
|
cmd: "ffmpeg",
|
|
@@ -12192,39 +12531,39 @@ function findMicCaptureCommand() {
|
|
|
12192
12531
|
function findLiveWhisperScript() {
|
|
12193
12532
|
const thisDir = dirname6(fileURLToPath3(import.meta.url));
|
|
12194
12533
|
const candidates = [
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12534
|
+
join20(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
|
|
12535
|
+
join20(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
|
|
12536
|
+
join20(thisDir, "../../execution/scripts/live-whisper.py"),
|
|
12198
12537
|
// npm install layout — scripts bundled alongside dist
|
|
12199
|
-
|
|
12200
|
-
|
|
12538
|
+
join20(thisDir, "../scripts/live-whisper.py"),
|
|
12539
|
+
join20(thisDir, "../../scripts/live-whisper.py")
|
|
12201
12540
|
];
|
|
12202
12541
|
for (const p of candidates) {
|
|
12203
|
-
if (
|
|
12542
|
+
if (existsSync15(p))
|
|
12204
12543
|
return p;
|
|
12205
12544
|
}
|
|
12206
12545
|
try {
|
|
12207
|
-
const globalRoot =
|
|
12546
|
+
const globalRoot = execSync14("npm root -g", {
|
|
12208
12547
|
encoding: "utf-8",
|
|
12209
12548
|
timeout: 5e3,
|
|
12210
12549
|
stdio: ["pipe", "pipe", "pipe"]
|
|
12211
12550
|
}).trim();
|
|
12212
12551
|
const candidates2 = [
|
|
12213
|
-
|
|
12214
|
-
|
|
12552
|
+
join20(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
|
|
12553
|
+
join20(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
|
|
12215
12554
|
];
|
|
12216
12555
|
for (const p of candidates2) {
|
|
12217
|
-
if (
|
|
12556
|
+
if (existsSync15(p))
|
|
12218
12557
|
return p;
|
|
12219
12558
|
}
|
|
12220
12559
|
} catch {
|
|
12221
12560
|
}
|
|
12222
|
-
const nvmBase =
|
|
12223
|
-
if (
|
|
12561
|
+
const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
|
|
12562
|
+
if (existsSync15(nvmBase)) {
|
|
12224
12563
|
try {
|
|
12225
12564
|
for (const ver of readdirSync6(nvmBase)) {
|
|
12226
|
-
const p =
|
|
12227
|
-
if (
|
|
12565
|
+
const p = join20(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
|
|
12566
|
+
if (existsSync15(p))
|
|
12228
12567
|
return p;
|
|
12229
12568
|
}
|
|
12230
12569
|
} catch {
|
|
@@ -12237,21 +12576,21 @@ function ensureTranscribeCliBackground() {
|
|
|
12237
12576
|
return;
|
|
12238
12577
|
_bgInstallPromise = (async () => {
|
|
12239
12578
|
try {
|
|
12240
|
-
const globalRoot =
|
|
12579
|
+
const globalRoot = execSync14("npm root -g", {
|
|
12241
12580
|
encoding: "utf-8",
|
|
12242
12581
|
timeout: 5e3,
|
|
12243
12582
|
stdio: ["pipe", "pipe", "pipe"]
|
|
12244
12583
|
}).trim();
|
|
12245
|
-
if (
|
|
12584
|
+
if (existsSync15(join20(globalRoot, "transcribe-cli", "dist", "index.js"))) {
|
|
12246
12585
|
return true;
|
|
12247
12586
|
}
|
|
12248
12587
|
} catch {
|
|
12249
12588
|
}
|
|
12250
12589
|
try {
|
|
12251
12590
|
const { exec } = await import("node:child_process");
|
|
12252
|
-
return new Promise((
|
|
12591
|
+
return new Promise((resolve21) => {
|
|
12253
12592
|
exec("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
|
|
12254
|
-
|
|
12593
|
+
resolve21(!err);
|
|
12255
12594
|
});
|
|
12256
12595
|
});
|
|
12257
12596
|
} catch {
|
|
@@ -12304,7 +12643,7 @@ var init_listen = __esm({
|
|
|
12304
12643
|
return this._ready;
|
|
12305
12644
|
}
|
|
12306
12645
|
async start() {
|
|
12307
|
-
return new Promise((
|
|
12646
|
+
return new Promise((resolve21, reject) => {
|
|
12308
12647
|
const timeout = setTimeout(() => {
|
|
12309
12648
|
reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
|
|
12310
12649
|
}, 3e5);
|
|
@@ -12332,7 +12671,7 @@ var init_listen = __esm({
|
|
|
12332
12671
|
this._ready = true;
|
|
12333
12672
|
clearTimeout(timeout);
|
|
12334
12673
|
this.emit("ready");
|
|
12335
|
-
|
|
12674
|
+
resolve21();
|
|
12336
12675
|
break;
|
|
12337
12676
|
case "transcript":
|
|
12338
12677
|
this.emit("transcript", {
|
|
@@ -12437,7 +12776,7 @@ var init_listen = __esm({
|
|
|
12437
12776
|
}
|
|
12438
12777
|
if (!this.transcribeCliAvailable) {
|
|
12439
12778
|
try {
|
|
12440
|
-
|
|
12779
|
+
execSync14("which transcribe-cli", { stdio: "pipe" });
|
|
12441
12780
|
this.transcribeCliAvailable = true;
|
|
12442
12781
|
} catch {
|
|
12443
12782
|
this.transcribeCliAvailable = false;
|
|
@@ -12454,29 +12793,29 @@ var init_listen = __esm({
|
|
|
12454
12793
|
} catch {
|
|
12455
12794
|
}
|
|
12456
12795
|
try {
|
|
12457
|
-
const globalRoot =
|
|
12796
|
+
const globalRoot = execSync14("npm root -g", {
|
|
12458
12797
|
encoding: "utf-8",
|
|
12459
12798
|
timeout: 5e3,
|
|
12460
12799
|
stdio: ["pipe", "pipe", "pipe"]
|
|
12461
12800
|
}).trim();
|
|
12462
|
-
const tcPath =
|
|
12463
|
-
if (
|
|
12801
|
+
const tcPath = join20(globalRoot, "transcribe-cli");
|
|
12802
|
+
if (existsSync15(join20(tcPath, "dist", "index.js"))) {
|
|
12464
12803
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
12465
12804
|
const req = createRequire4(import.meta.url);
|
|
12466
|
-
return req(
|
|
12805
|
+
return req(join20(tcPath, "dist", "index.js"));
|
|
12467
12806
|
}
|
|
12468
12807
|
} catch {
|
|
12469
12808
|
}
|
|
12470
|
-
const nvmBase =
|
|
12471
|
-
if (
|
|
12809
|
+
const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
|
|
12810
|
+
if (existsSync15(nvmBase)) {
|
|
12472
12811
|
try {
|
|
12473
12812
|
const { readdirSync: readdirSync11 } = await import("node:fs");
|
|
12474
12813
|
for (const ver of readdirSync11(nvmBase)) {
|
|
12475
|
-
const tcPath =
|
|
12476
|
-
if (
|
|
12814
|
+
const tcPath = join20(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
12815
|
+
if (existsSync15(join20(tcPath, "dist", "index.js"))) {
|
|
12477
12816
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
12478
12817
|
const req = createRequire4(import.meta.url);
|
|
12479
|
-
return req(
|
|
12818
|
+
return req(join20(tcPath, "dist", "index.js"));
|
|
12480
12819
|
}
|
|
12481
12820
|
}
|
|
12482
12821
|
} catch {
|
|
@@ -12504,7 +12843,7 @@ var init_listen = __esm({
|
|
|
12504
12843
|
}
|
|
12505
12844
|
if (!tc) {
|
|
12506
12845
|
try {
|
|
12507
|
-
|
|
12846
|
+
execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
12508
12847
|
this.transcribeCliAvailable = null;
|
|
12509
12848
|
tc = await this.loadTranscribeCli();
|
|
12510
12849
|
} catch {
|
|
@@ -12536,11 +12875,11 @@ var init_listen = __esm({
|
|
|
12536
12875
|
this.liveTranscriber.on("error", (err) => {
|
|
12537
12876
|
this.emit("error", err);
|
|
12538
12877
|
});
|
|
12539
|
-
await new Promise((
|
|
12878
|
+
await new Promise((resolve21, reject) => {
|
|
12540
12879
|
const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
|
|
12541
12880
|
this.liveTranscriber.on("ready", () => {
|
|
12542
12881
|
clearTimeout(timeout);
|
|
12543
|
-
|
|
12882
|
+
resolve21();
|
|
12544
12883
|
});
|
|
12545
12884
|
this.liveTranscriber.on("error", (err) => {
|
|
12546
12885
|
clearTimeout(timeout);
|
|
@@ -12685,7 +13024,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
12685
13024
|
}
|
|
12686
13025
|
if (!tc) {
|
|
12687
13026
|
try {
|
|
12688
|
-
|
|
13027
|
+
execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
12689
13028
|
this.transcribeCliAvailable = null;
|
|
12690
13029
|
tc = await this.loadTranscribeCli();
|
|
12691
13030
|
} catch {
|
|
@@ -12701,10 +13040,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
12701
13040
|
wordTimestamps: false
|
|
12702
13041
|
});
|
|
12703
13042
|
if (outputDir) {
|
|
12704
|
-
const { basename:
|
|
12705
|
-
const transcriptDir =
|
|
13043
|
+
const { basename: basename12 } = await import("node:path");
|
|
13044
|
+
const transcriptDir = join20(outputDir, ".oa", "transcripts");
|
|
12706
13045
|
mkdirSync5(transcriptDir, { recursive: true });
|
|
12707
|
-
const outFile =
|
|
13046
|
+
const outFile = join20(transcriptDir, `${basename12(filePath)}.txt`);
|
|
12708
13047
|
writeFileSync5(outFile, result.text, "utf-8");
|
|
12709
13048
|
}
|
|
12710
13049
|
return {
|
|
@@ -13968,7 +14307,7 @@ Approach this task thoughtfully:
|
|
|
13968
14307
|
});
|
|
13969
14308
|
|
|
13970
14309
|
// packages/prompts/dist/index.js
|
|
13971
|
-
import { join as
|
|
14310
|
+
import { join as join21, dirname as dirname7 } from "node:path";
|
|
13972
14311
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
13973
14312
|
var _dir, _packageRoot;
|
|
13974
14313
|
var init_dist6 = __esm({
|
|
@@ -13979,57 +14318,57 @@ var init_dist6 = __esm({
|
|
|
13979
14318
|
init_task_templates();
|
|
13980
14319
|
init_render2();
|
|
13981
14320
|
_dir = dirname7(fileURLToPath4(import.meta.url));
|
|
13982
|
-
_packageRoot =
|
|
14321
|
+
_packageRoot = join21(_dir, "..");
|
|
13983
14322
|
}
|
|
13984
14323
|
});
|
|
13985
14324
|
|
|
13986
14325
|
// packages/cli/dist/tui/oa-directory.js
|
|
13987
|
-
import { existsSync as
|
|
13988
|
-
import { join as
|
|
14326
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync8, unlinkSync as unlinkSync3 } from "node:fs";
|
|
14327
|
+
import { join as join22, relative as relative2, basename as basename7, extname as extname8 } from "node:path";
|
|
13989
14328
|
import { homedir as homedir7 } from "node:os";
|
|
13990
14329
|
function initOaDirectory(repoRoot) {
|
|
13991
|
-
const oaPath =
|
|
14330
|
+
const oaPath = join22(repoRoot, OA_DIR);
|
|
13992
14331
|
for (const sub of SUBDIRS) {
|
|
13993
|
-
mkdirSync6(
|
|
14332
|
+
mkdirSync6(join22(oaPath, sub), { recursive: true });
|
|
13994
14333
|
}
|
|
13995
14334
|
return oaPath;
|
|
13996
14335
|
}
|
|
13997
14336
|
function hasOaDirectory(repoRoot) {
|
|
13998
|
-
return
|
|
14337
|
+
return existsSync16(join22(repoRoot, OA_DIR, "index"));
|
|
13999
14338
|
}
|
|
14000
14339
|
function loadProjectSettings(repoRoot) {
|
|
14001
|
-
const settingsPath =
|
|
14340
|
+
const settingsPath = join22(repoRoot, OA_DIR, "settings.json");
|
|
14002
14341
|
try {
|
|
14003
|
-
if (
|
|
14004
|
-
return JSON.parse(
|
|
14342
|
+
if (existsSync16(settingsPath)) {
|
|
14343
|
+
return JSON.parse(readFileSync13(settingsPath, "utf-8"));
|
|
14005
14344
|
}
|
|
14006
14345
|
} catch {
|
|
14007
14346
|
}
|
|
14008
14347
|
return {};
|
|
14009
14348
|
}
|
|
14010
14349
|
function saveProjectSettings(repoRoot, settings) {
|
|
14011
|
-
const oaPath =
|
|
14350
|
+
const oaPath = join22(repoRoot, OA_DIR);
|
|
14012
14351
|
mkdirSync6(oaPath, { recursive: true });
|
|
14013
14352
|
const existing = loadProjectSettings(repoRoot);
|
|
14014
14353
|
const merged = { ...existing, ...settings };
|
|
14015
|
-
writeFileSync6(
|
|
14354
|
+
writeFileSync6(join22(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
14016
14355
|
}
|
|
14017
14356
|
function loadGlobalSettings() {
|
|
14018
|
-
const settingsPath =
|
|
14357
|
+
const settingsPath = join22(homedir7(), ".open-agents", "settings.json");
|
|
14019
14358
|
try {
|
|
14020
|
-
if (
|
|
14021
|
-
return JSON.parse(
|
|
14359
|
+
if (existsSync16(settingsPath)) {
|
|
14360
|
+
return JSON.parse(readFileSync13(settingsPath, "utf-8"));
|
|
14022
14361
|
}
|
|
14023
14362
|
} catch {
|
|
14024
14363
|
}
|
|
14025
14364
|
return {};
|
|
14026
14365
|
}
|
|
14027
14366
|
function saveGlobalSettings(settings) {
|
|
14028
|
-
const dir =
|
|
14367
|
+
const dir = join22(homedir7(), ".open-agents");
|
|
14029
14368
|
mkdirSync6(dir, { recursive: true });
|
|
14030
14369
|
const existing = loadGlobalSettings();
|
|
14031
14370
|
const merged = { ...existing, ...settings };
|
|
14032
|
-
writeFileSync6(
|
|
14371
|
+
writeFileSync6(join22(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
14033
14372
|
}
|
|
14034
14373
|
function resolveSettings(repoRoot) {
|
|
14035
14374
|
const global = loadGlobalSettings();
|
|
@@ -14044,12 +14383,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
14044
14383
|
while (dir && !visited.has(dir)) {
|
|
14045
14384
|
visited.add(dir);
|
|
14046
14385
|
for (const name of CONTEXT_FILES) {
|
|
14047
|
-
const filePath =
|
|
14386
|
+
const filePath = join22(dir, name);
|
|
14048
14387
|
const normalizedName = name.toLowerCase();
|
|
14049
|
-
if (
|
|
14388
|
+
if (existsSync16(filePath) && !seen.has(filePath)) {
|
|
14050
14389
|
seen.add(filePath);
|
|
14051
14390
|
try {
|
|
14052
|
-
let content =
|
|
14391
|
+
let content = readFileSync13(filePath, "utf-8");
|
|
14053
14392
|
if (content.length > maxContentLen) {
|
|
14054
14393
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
14055
14394
|
}
|
|
@@ -14063,11 +14402,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
14063
14402
|
}
|
|
14064
14403
|
}
|
|
14065
14404
|
}
|
|
14066
|
-
const projectMap =
|
|
14067
|
-
if (
|
|
14405
|
+
const projectMap = join22(dir, OA_DIR, "context", "project-map.md");
|
|
14406
|
+
if (existsSync16(projectMap) && !seen.has(projectMap)) {
|
|
14068
14407
|
seen.add(projectMap);
|
|
14069
14408
|
try {
|
|
14070
|
-
let content =
|
|
14409
|
+
let content = readFileSync13(projectMap, "utf-8");
|
|
14071
14410
|
if (content.length > maxContentLen) {
|
|
14072
14411
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
14073
14412
|
}
|
|
@@ -14079,7 +14418,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
14079
14418
|
} catch {
|
|
14080
14419
|
}
|
|
14081
14420
|
}
|
|
14082
|
-
const parent =
|
|
14421
|
+
const parent = join22(dir, "..");
|
|
14083
14422
|
if (parent === dir)
|
|
14084
14423
|
break;
|
|
14085
14424
|
dir = parent;
|
|
@@ -14097,16 +14436,16 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
14097
14436
|
return found;
|
|
14098
14437
|
}
|
|
14099
14438
|
function readIndexMeta(repoRoot) {
|
|
14100
|
-
const metaPath =
|
|
14439
|
+
const metaPath = join22(repoRoot, OA_DIR, "index", "meta.json");
|
|
14101
14440
|
try {
|
|
14102
|
-
return JSON.parse(
|
|
14441
|
+
return JSON.parse(readFileSync13(metaPath, "utf-8"));
|
|
14103
14442
|
} catch {
|
|
14104
14443
|
return null;
|
|
14105
14444
|
}
|
|
14106
14445
|
}
|
|
14107
14446
|
function generateProjectMap(repoRoot) {
|
|
14108
14447
|
const sections = [];
|
|
14109
|
-
const repoName2 =
|
|
14448
|
+
const repoName2 = basename7(repoRoot);
|
|
14110
14449
|
sections.push(`# Project Map: ${repoName2}
|
|
14111
14450
|
`);
|
|
14112
14451
|
sections.push(`> Auto-generated by open-agents. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -14150,49 +14489,49 @@ ${tree}\`\`\`
|
|
|
14150
14489
|
sections.push("");
|
|
14151
14490
|
}
|
|
14152
14491
|
const content = sections.join("\n");
|
|
14153
|
-
const contextDir =
|
|
14492
|
+
const contextDir = join22(repoRoot, OA_DIR, "context");
|
|
14154
14493
|
mkdirSync6(contextDir, { recursive: true });
|
|
14155
|
-
writeFileSync6(
|
|
14494
|
+
writeFileSync6(join22(contextDir, "project-map.md"), content, "utf-8");
|
|
14156
14495
|
return content;
|
|
14157
14496
|
}
|
|
14158
14497
|
function saveSession(repoRoot, session) {
|
|
14159
|
-
const historyDir =
|
|
14498
|
+
const historyDir = join22(repoRoot, OA_DIR, "history");
|
|
14160
14499
|
mkdirSync6(historyDir, { recursive: true });
|
|
14161
|
-
writeFileSync6(
|
|
14500
|
+
writeFileSync6(join22(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
14162
14501
|
}
|
|
14163
14502
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
14164
|
-
const historyDir =
|
|
14165
|
-
if (!
|
|
14503
|
+
const historyDir = join22(repoRoot, OA_DIR, "history");
|
|
14504
|
+
if (!existsSync16(historyDir))
|
|
14166
14505
|
return [];
|
|
14167
14506
|
try {
|
|
14168
|
-
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
14169
|
-
const stat5 =
|
|
14507
|
+
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
14508
|
+
const stat5 = statSync8(join22(historyDir, f));
|
|
14170
14509
|
return { file: f, mtime: stat5.mtimeMs };
|
|
14171
14510
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
14172
14511
|
return files.map((f) => {
|
|
14173
14512
|
try {
|
|
14174
|
-
return JSON.parse(
|
|
14513
|
+
return JSON.parse(readFileSync13(join22(historyDir, f.file), "utf-8"));
|
|
14175
14514
|
} catch {
|
|
14176
14515
|
return null;
|
|
14177
14516
|
}
|
|
14178
|
-
}).filter((s) => s !== null);
|
|
14517
|
+
}).filter((s) => s !== null && typeof s.startedAt === "string" && typeof s.task === "string");
|
|
14179
14518
|
} catch {
|
|
14180
14519
|
return [];
|
|
14181
14520
|
}
|
|
14182
14521
|
}
|
|
14183
14522
|
function savePendingTask(repoRoot, task) {
|
|
14184
|
-
const historyDir =
|
|
14523
|
+
const historyDir = join22(repoRoot, OA_DIR, "history");
|
|
14185
14524
|
mkdirSync6(historyDir, { recursive: true });
|
|
14186
|
-
writeFileSync6(
|
|
14525
|
+
writeFileSync6(join22(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
14187
14526
|
}
|
|
14188
14527
|
function loadPendingTask(repoRoot) {
|
|
14189
|
-
const filePath =
|
|
14528
|
+
const filePath = join22(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
14190
14529
|
try {
|
|
14191
|
-
if (!
|
|
14530
|
+
if (!existsSync16(filePath))
|
|
14192
14531
|
return null;
|
|
14193
|
-
const data = JSON.parse(
|
|
14532
|
+
const data = JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
14194
14533
|
try {
|
|
14195
|
-
|
|
14534
|
+
unlinkSync3(filePath);
|
|
14196
14535
|
} catch {
|
|
14197
14536
|
}
|
|
14198
14537
|
return data;
|
|
@@ -14218,12 +14557,12 @@ function detectManifests(repoRoot) {
|
|
|
14218
14557
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
14219
14558
|
];
|
|
14220
14559
|
for (const check of checks) {
|
|
14221
|
-
const filePath =
|
|
14222
|
-
if (
|
|
14560
|
+
const filePath = join22(repoRoot, check.file);
|
|
14561
|
+
if (existsSync16(filePath)) {
|
|
14223
14562
|
let name;
|
|
14224
14563
|
if (check.nameField) {
|
|
14225
14564
|
try {
|
|
14226
|
-
const data = JSON.parse(
|
|
14565
|
+
const data = JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
14227
14566
|
name = data[check.nameField];
|
|
14228
14567
|
} catch {
|
|
14229
14568
|
}
|
|
@@ -14252,7 +14591,7 @@ function findKeyFiles(repoRoot) {
|
|
|
14252
14591
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
14253
14592
|
];
|
|
14254
14593
|
for (const check of checks) {
|
|
14255
|
-
if (
|
|
14594
|
+
if (existsSync16(join22(repoRoot, check.pattern))) {
|
|
14256
14595
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
14257
14596
|
}
|
|
14258
14597
|
}
|
|
@@ -14278,12 +14617,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
14278
14617
|
if (entry.isDirectory()) {
|
|
14279
14618
|
let fileCount = 0;
|
|
14280
14619
|
try {
|
|
14281
|
-
fileCount = readdirSync7(
|
|
14620
|
+
fileCount = readdirSync7(join22(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
14282
14621
|
} catch {
|
|
14283
14622
|
}
|
|
14284
14623
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
14285
14624
|
`;
|
|
14286
|
-
result += buildDirTree(
|
|
14625
|
+
result += buildDirTree(join22(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
14287
14626
|
} else if (depth < maxDepth) {
|
|
14288
14627
|
result += `${prefix}${connector}${entry.name}
|
|
14289
14628
|
`;
|
|
@@ -14334,9 +14673,9 @@ var init_oa_directory = __esm({
|
|
|
14334
14673
|
|
|
14335
14674
|
// packages/cli/dist/tui/setup.js
|
|
14336
14675
|
import * as readline from "node:readline";
|
|
14337
|
-
import { execSync as
|
|
14338
|
-
import { existsSync as
|
|
14339
|
-
import { join as
|
|
14676
|
+
import { execSync as execSync15, spawn as spawn8 } from "node:child_process";
|
|
14677
|
+
import { existsSync as existsSync17, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
14678
|
+
import { join as join23 } from "node:path";
|
|
14340
14679
|
import { homedir as homedir8, platform } from "node:os";
|
|
14341
14680
|
function detectSystemSpecs() {
|
|
14342
14681
|
let totalRamGB = 0;
|
|
@@ -14344,7 +14683,7 @@ function detectSystemSpecs() {
|
|
|
14344
14683
|
let gpuVramGB = 0;
|
|
14345
14684
|
let gpuName = "";
|
|
14346
14685
|
try {
|
|
14347
|
-
const memInfo =
|
|
14686
|
+
const memInfo = execSync15("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
14348
14687
|
encoding: "utf8",
|
|
14349
14688
|
timeout: 5e3
|
|
14350
14689
|
});
|
|
@@ -14364,7 +14703,7 @@ function detectSystemSpecs() {
|
|
|
14364
14703
|
} catch {
|
|
14365
14704
|
}
|
|
14366
14705
|
try {
|
|
14367
|
-
const nvidiaSmi =
|
|
14706
|
+
const nvidiaSmi = execSync15("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
14368
14707
|
const lines = nvidiaSmi.trim().split("\n");
|
|
14369
14708
|
if (lines.length > 0) {
|
|
14370
14709
|
for (const line of lines) {
|
|
@@ -14420,8 +14759,8 @@ function modelSupportsToolCalling(modelName) {
|
|
|
14420
14759
|
return false;
|
|
14421
14760
|
}
|
|
14422
14761
|
function ask(rl, question) {
|
|
14423
|
-
return new Promise((
|
|
14424
|
-
rl.question(question, (answer) =>
|
|
14762
|
+
return new Promise((resolve21) => {
|
|
14763
|
+
rl.question(question, (answer) => resolve21(answer.trim()));
|
|
14425
14764
|
});
|
|
14426
14765
|
}
|
|
14427
14766
|
async function autoInstallOllama(rl) {
|
|
@@ -14446,7 +14785,7 @@ function installOllamaLinux() {
|
|
|
14446
14785
|
|
|
14447
14786
|
`);
|
|
14448
14787
|
try {
|
|
14449
|
-
|
|
14788
|
+
execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
14450
14789
|
stdio: "inherit",
|
|
14451
14790
|
timeout: 3e5
|
|
14452
14791
|
});
|
|
@@ -14485,10 +14824,10 @@ async function installOllamaMac(rl) {
|
|
|
14485
14824
|
|
|
14486
14825
|
`);
|
|
14487
14826
|
try {
|
|
14488
|
-
|
|
14827
|
+
execSync15('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
14489
14828
|
if (!hasCmd("brew")) {
|
|
14490
14829
|
try {
|
|
14491
|
-
const brewPrefix =
|
|
14830
|
+
const brewPrefix = existsSync17("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
14492
14831
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
14493
14832
|
} catch {
|
|
14494
14833
|
}
|
|
@@ -14518,7 +14857,7 @@ async function installOllamaMac(rl) {
|
|
|
14518
14857
|
|
|
14519
14858
|
`);
|
|
14520
14859
|
try {
|
|
14521
|
-
|
|
14860
|
+
execSync15("brew install ollama", {
|
|
14522
14861
|
stdio: "inherit",
|
|
14523
14862
|
timeout: 3e5
|
|
14524
14863
|
});
|
|
@@ -14545,7 +14884,7 @@ function installOllamaWindows() {
|
|
|
14545
14884
|
|
|
14546
14885
|
`);
|
|
14547
14886
|
try {
|
|
14548
|
-
|
|
14887
|
+
execSync15('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
14549
14888
|
stdio: "inherit",
|
|
14550
14889
|
timeout: 3e5
|
|
14551
14890
|
});
|
|
@@ -14568,7 +14907,7 @@ function installOllamaWindows() {
|
|
|
14568
14907
|
}
|
|
14569
14908
|
function pullModelWithAutoUpdate(tag) {
|
|
14570
14909
|
try {
|
|
14571
|
-
|
|
14910
|
+
execSync15(`ollama pull ${tag}`, {
|
|
14572
14911
|
stdio: "inherit",
|
|
14573
14912
|
timeout: 36e5
|
|
14574
14913
|
// 1 hour max
|
|
@@ -14585,7 +14924,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
14585
14924
|
|
|
14586
14925
|
`);
|
|
14587
14926
|
try {
|
|
14588
|
-
|
|
14927
|
+
execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
14589
14928
|
stdio: "inherit",
|
|
14590
14929
|
timeout: 3e5
|
|
14591
14930
|
// 5 min max for install
|
|
@@ -14596,7 +14935,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
14596
14935
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
14597
14936
|
|
|
14598
14937
|
`);
|
|
14599
|
-
|
|
14938
|
+
execSync15(`ollama pull ${tag}`, {
|
|
14600
14939
|
stdio: "inherit",
|
|
14601
14940
|
timeout: 36e5
|
|
14602
14941
|
});
|
|
@@ -14779,7 +15118,7 @@ async function doSetup(config, rl) {
|
|
|
14779
15118
|
try {
|
|
14780
15119
|
const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
14781
15120
|
child.unref();
|
|
14782
|
-
await new Promise((
|
|
15121
|
+
await new Promise((resolve21) => setTimeout(resolve21, 3e3));
|
|
14783
15122
|
try {
|
|
14784
15123
|
models = await fetchOllamaModels(config.backendUrl);
|
|
14785
15124
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -14807,7 +15146,7 @@ async function doSetup(config, rl) {
|
|
|
14807
15146
|
try {
|
|
14808
15147
|
const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
14809
15148
|
child.unref();
|
|
14810
|
-
await new Promise((
|
|
15149
|
+
await new Promise((resolve21) => setTimeout(resolve21, 3e3));
|
|
14811
15150
|
try {
|
|
14812
15151
|
models = await fetchOllamaModels(config.backendUrl);
|
|
14813
15152
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -14961,12 +15300,12 @@ async function doSetup(config, rl) {
|
|
|
14961
15300
|
`PARAMETER num_predict 16384`,
|
|
14962
15301
|
`PARAMETER stop "<|endoftext|>"`
|
|
14963
15302
|
].join("\n");
|
|
14964
|
-
const modelDir2 =
|
|
15303
|
+
const modelDir2 = join23(homedir8(), ".open-agents", "models");
|
|
14965
15304
|
mkdirSync7(modelDir2, { recursive: true });
|
|
14966
|
-
const modelfilePath =
|
|
15305
|
+
const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
|
|
14967
15306
|
writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
|
|
14968
15307
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
14969
|
-
|
|
15308
|
+
execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
14970
15309
|
stdio: "pipe",
|
|
14971
15310
|
timeout: 12e4
|
|
14972
15311
|
});
|
|
@@ -15009,20 +15348,32 @@ async function isModelAvailable(config) {
|
|
|
15009
15348
|
}
|
|
15010
15349
|
function isFirstRun() {
|
|
15011
15350
|
try {
|
|
15012
|
-
return !
|
|
15351
|
+
return !existsSync17(join23(homedir8(), ".open-agents", "config.json"));
|
|
15013
15352
|
} catch {
|
|
15014
15353
|
return true;
|
|
15015
15354
|
}
|
|
15016
15355
|
}
|
|
15017
15356
|
function hasCmd(cmd) {
|
|
15018
15357
|
try {
|
|
15019
|
-
|
|
15358
|
+
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
15359
|
+
execSync15(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
15020
15360
|
return true;
|
|
15021
15361
|
} catch {
|
|
15022
15362
|
return false;
|
|
15023
15363
|
}
|
|
15024
15364
|
}
|
|
15025
15365
|
function detectPkgManager() {
|
|
15366
|
+
const plat = process.platform;
|
|
15367
|
+
if (plat === "win32") {
|
|
15368
|
+
if (hasCmd("choco"))
|
|
15369
|
+
return "choco";
|
|
15370
|
+
return null;
|
|
15371
|
+
}
|
|
15372
|
+
if (plat === "darwin") {
|
|
15373
|
+
if (hasCmd("brew"))
|
|
15374
|
+
return "brew";
|
|
15375
|
+
return null;
|
|
15376
|
+
}
|
|
15026
15377
|
if (hasCmd("apt-get"))
|
|
15027
15378
|
return "apt";
|
|
15028
15379
|
if (hasCmd("dnf"))
|
|
@@ -15034,11 +15385,11 @@ function detectPkgManager() {
|
|
|
15034
15385
|
return null;
|
|
15035
15386
|
}
|
|
15036
15387
|
function getVenvDir() {
|
|
15037
|
-
return
|
|
15388
|
+
return join23(homedir8(), ".open-agents", "venv");
|
|
15038
15389
|
}
|
|
15039
15390
|
function hasVenvModule() {
|
|
15040
15391
|
try {
|
|
15041
|
-
|
|
15392
|
+
execSync15("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
15042
15393
|
return true;
|
|
15043
15394
|
} catch {
|
|
15044
15395
|
return false;
|
|
@@ -15046,8 +15397,8 @@ function hasVenvModule() {
|
|
|
15046
15397
|
}
|
|
15047
15398
|
function ensureVenv(log) {
|
|
15048
15399
|
const venvDir = getVenvDir();
|
|
15049
|
-
const venvPip =
|
|
15050
|
-
if (
|
|
15400
|
+
const venvPip = join23(venvDir, "bin", "pip");
|
|
15401
|
+
if (existsSync17(venvPip))
|
|
15051
15402
|
return venvDir;
|
|
15052
15403
|
log("Creating Python venv for vision deps...");
|
|
15053
15404
|
if (!hasCmd("python3")) {
|
|
@@ -15059,9 +15410,9 @@ function ensureVenv(log) {
|
|
|
15059
15410
|
return null;
|
|
15060
15411
|
}
|
|
15061
15412
|
try {
|
|
15062
|
-
mkdirSync7(
|
|
15063
|
-
|
|
15064
|
-
|
|
15413
|
+
mkdirSync7(join23(homedir8(), ".open-agents"), { recursive: true });
|
|
15414
|
+
execSync15(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
15415
|
+
execSync15(`"${join23(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
15065
15416
|
stdio: "pipe",
|
|
15066
15417
|
timeout: 6e4
|
|
15067
15418
|
});
|
|
@@ -15074,7 +15425,7 @@ function ensureVenv(log) {
|
|
|
15074
15425
|
}
|
|
15075
15426
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
15076
15427
|
try {
|
|
15077
|
-
|
|
15428
|
+
execSync15(`sudo -n ${cmd}`, {
|
|
15078
15429
|
stdio: "pipe",
|
|
15079
15430
|
timeout: timeoutMs,
|
|
15080
15431
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -15086,7 +15437,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
15086
15437
|
}
|
|
15087
15438
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
15088
15439
|
try {
|
|
15089
|
-
|
|
15440
|
+
execSync15(`sudo -S ${cmd}`, {
|
|
15090
15441
|
input: password + "\n",
|
|
15091
15442
|
stdio: ["pipe", "pipe", "pipe"],
|
|
15092
15443
|
timeout: timeoutMs,
|
|
@@ -15131,7 +15482,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15131
15482
|
apt: { cmd: "apt-get install -y tesseract-ocr", needsSudo: true },
|
|
15132
15483
|
dnf: { cmd: "dnf install -y tesseract", needsSudo: true },
|
|
15133
15484
|
pacman: { cmd: "pacman -S --noconfirm tesseract", needsSudo: true },
|
|
15134
|
-
brew: { cmd: "brew install tesseract", needsSudo: false }
|
|
15485
|
+
brew: { cmd: "brew install tesseract", needsSudo: false },
|
|
15486
|
+
choco: { cmd: "choco install -y tesseract", needsSudo: false }
|
|
15135
15487
|
};
|
|
15136
15488
|
const pkg = pkgMap[pm2];
|
|
15137
15489
|
if (pkg.needsSudo) {
|
|
@@ -15145,7 +15497,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15145
15497
|
} else {
|
|
15146
15498
|
log("Installing tesseract-ocr...");
|
|
15147
15499
|
try {
|
|
15148
|
-
|
|
15500
|
+
execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
15149
15501
|
if (hasCmd("tesseract")) {
|
|
15150
15502
|
log("tesseract-ocr installed successfully.");
|
|
15151
15503
|
} else {
|
|
@@ -15159,6 +15511,76 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15159
15511
|
log("No supported package manager detected \u2014 tesseract OCR unavailable.");
|
|
15160
15512
|
}
|
|
15161
15513
|
}
|
|
15514
|
+
const pdfDeps = [
|
|
15515
|
+
{
|
|
15516
|
+
binary: "pdftotext",
|
|
15517
|
+
label: "poppler-utils (pdftotext)",
|
|
15518
|
+
pkgMap: {
|
|
15519
|
+
apt: { cmd: "apt-get install -y poppler-utils", needsSudo: true },
|
|
15520
|
+
dnf: { cmd: "dnf install -y poppler-utils", needsSudo: true },
|
|
15521
|
+
pacman: { cmd: "pacman -S --noconfirm poppler", needsSudo: true },
|
|
15522
|
+
brew: { cmd: "brew install poppler", needsSudo: false },
|
|
15523
|
+
choco: { cmd: "choco install -y poppler", needsSudo: false }
|
|
15524
|
+
}
|
|
15525
|
+
},
|
|
15526
|
+
{
|
|
15527
|
+
binary: "gs",
|
|
15528
|
+
label: "ghostscript",
|
|
15529
|
+
pkgMap: {
|
|
15530
|
+
apt: { cmd: "apt-get install -y ghostscript", needsSudo: true },
|
|
15531
|
+
dnf: { cmd: "dnf install -y ghostscript", needsSudo: true },
|
|
15532
|
+
pacman: { cmd: "pacman -S --noconfirm ghostscript", needsSudo: true },
|
|
15533
|
+
brew: { cmd: "brew install ghostscript", needsSudo: false },
|
|
15534
|
+
choco: { cmd: "choco install -y ghostscript", needsSudo: false }
|
|
15535
|
+
}
|
|
15536
|
+
},
|
|
15537
|
+
{
|
|
15538
|
+
binary: "ocrmypdf",
|
|
15539
|
+
label: "ocrmypdf",
|
|
15540
|
+
pkgMap: {
|
|
15541
|
+
apt: { cmd: "apt-get install -y ocrmypdf", needsSudo: true },
|
|
15542
|
+
dnf: { cmd: "dnf install -y ocrmypdf", needsSudo: true },
|
|
15543
|
+
pacman: { cmd: "pacman -S --noconfirm ocrmypdf", needsSudo: true },
|
|
15544
|
+
brew: { cmd: "brew install ocrmypdf", needsSudo: false },
|
|
15545
|
+
choco: { cmd: "choco install -y ocrmypdf", needsSudo: false }
|
|
15546
|
+
}
|
|
15547
|
+
}
|
|
15548
|
+
];
|
|
15549
|
+
{
|
|
15550
|
+
const pm2 = detectPkgManager();
|
|
15551
|
+
for (const dep of pdfDeps) {
|
|
15552
|
+
if (hasCmd(dep.binary))
|
|
15553
|
+
continue;
|
|
15554
|
+
if (!pm2) {
|
|
15555
|
+
log(`No supported package manager detected \u2014 ${dep.label} unavailable.`);
|
|
15556
|
+
continue;
|
|
15557
|
+
}
|
|
15558
|
+
const pkg = dep.pkgMap[pm2];
|
|
15559
|
+
if (!pkg)
|
|
15560
|
+
continue;
|
|
15561
|
+
if (pkg.needsSudo) {
|
|
15562
|
+
log(`Installing ${dep.label}...`);
|
|
15563
|
+
const ok = await sudoInstall(pkg.cmd, getPassword, log, cachedPasswordRef);
|
|
15564
|
+
if (ok && hasCmd(dep.binary)) {
|
|
15565
|
+
log(`${dep.label} installed successfully.`);
|
|
15566
|
+
} else {
|
|
15567
|
+
log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
|
|
15568
|
+
}
|
|
15569
|
+
} else {
|
|
15570
|
+
log(`Installing ${dep.label}...`);
|
|
15571
|
+
try {
|
|
15572
|
+
execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
15573
|
+
if (hasCmd(dep.binary)) {
|
|
15574
|
+
log(`${dep.label} installed successfully.`);
|
|
15575
|
+
} else {
|
|
15576
|
+
log(`${dep.label} install completed but binary not found.`);
|
|
15577
|
+
}
|
|
15578
|
+
} catch {
|
|
15579
|
+
log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
|
|
15580
|
+
}
|
|
15581
|
+
}
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15162
15584
|
const pm = detectPkgManager();
|
|
15163
15585
|
if (!hasCmd("pip3") && !hasCmd("pip") && pm) {
|
|
15164
15586
|
const pipCmds = {
|
|
@@ -15178,7 +15600,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15178
15600
|
const venvCmds = {
|
|
15179
15601
|
apt: () => {
|
|
15180
15602
|
try {
|
|
15181
|
-
const pyVer =
|
|
15603
|
+
const pyVer = execSync15(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
15182
15604
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
15183
15605
|
} catch {
|
|
15184
15606
|
return "apt-get install -y python3-venv";
|
|
@@ -15199,9 +15621,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15199
15621
|
}
|
|
15200
15622
|
}
|
|
15201
15623
|
const venvDir = getVenvDir();
|
|
15202
|
-
const venvBin =
|
|
15203
|
-
const venvMoondream =
|
|
15204
|
-
if (hasCmd("moondream-station") ||
|
|
15624
|
+
const venvBin = join23(venvDir, "bin");
|
|
15625
|
+
const venvMoondream = join23(venvBin, "moondream-station");
|
|
15626
|
+
if (hasCmd("moondream-station") || existsSync17(venvMoondream)) {
|
|
15205
15627
|
return;
|
|
15206
15628
|
}
|
|
15207
15629
|
const venv = ensureVenv(log);
|
|
@@ -15209,15 +15631,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
15209
15631
|
log("Python venv unavailable \u2014 moondream-station will not be installed.");
|
|
15210
15632
|
return;
|
|
15211
15633
|
}
|
|
15212
|
-
const venvPip =
|
|
15634
|
+
const venvPip = join23(venvBin, "pip");
|
|
15213
15635
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
15214
15636
|
try {
|
|
15215
|
-
|
|
15216
|
-
if (
|
|
15637
|
+
execSync15(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
15638
|
+
if (existsSync17(venvMoondream)) {
|
|
15217
15639
|
log("moondream-station installed successfully.");
|
|
15218
15640
|
} else {
|
|
15219
15641
|
try {
|
|
15220
|
-
const check =
|
|
15642
|
+
const check = execSync15(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
15221
15643
|
if (check.includes("moondream")) {
|
|
15222
15644
|
log("moondream-station package installed.");
|
|
15223
15645
|
}
|
|
@@ -15262,11 +15684,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
15262
15684
|
`PARAMETER num_predict 16384`,
|
|
15263
15685
|
`PARAMETER stop "<|endoftext|>"`
|
|
15264
15686
|
].join("\n");
|
|
15265
|
-
const modelDir2 =
|
|
15687
|
+
const modelDir2 = join23(homedir8(), ".open-agents", "models");
|
|
15266
15688
|
mkdirSync7(modelDir2, { recursive: true });
|
|
15267
|
-
const modelfilePath =
|
|
15689
|
+
const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
|
|
15268
15690
|
writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
|
|
15269
|
-
|
|
15691
|
+
execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
15270
15692
|
stdio: "pipe",
|
|
15271
15693
|
timeout: 12e4
|
|
15272
15694
|
});
|
|
@@ -15954,17 +16376,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
15954
16376
|
try {
|
|
15955
16377
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
15956
16378
|
const { fileURLToPath: fileURLToPath7 } = await import("node:url");
|
|
15957
|
-
const { dirname: dirname10, join:
|
|
15958
|
-
const { existsSync:
|
|
16379
|
+
const { dirname: dirname10, join: join34 } = await import("node:path");
|
|
16380
|
+
const { existsSync: existsSync24 } = await import("node:fs");
|
|
15959
16381
|
const req = createRequire4(import.meta.url);
|
|
15960
16382
|
const thisDir = dirname10(fileURLToPath7(import.meta.url));
|
|
15961
16383
|
const candidates = [
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
16384
|
+
join34(thisDir, "..", "package.json"),
|
|
16385
|
+
join34(thisDir, "..", "..", "package.json"),
|
|
16386
|
+
join34(thisDir, "..", "..", "..", "package.json")
|
|
15965
16387
|
];
|
|
15966
16388
|
for (const pkgPath of candidates) {
|
|
15967
|
-
if (
|
|
16389
|
+
if (existsSync24(pkgPath)) {
|
|
15968
16390
|
const pkg = req(pkgPath);
|
|
15969
16391
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
15970
16392
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -15989,9 +16411,9 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
15989
16411
|
process.stdout.write(` ${c2.cyan("\u25CF")} Installing update...
|
|
15990
16412
|
|
|
15991
16413
|
`);
|
|
15992
|
-
const { execSync:
|
|
16414
|
+
const { execSync: execSync19 } = await import("node:child_process");
|
|
15993
16415
|
try {
|
|
15994
|
-
|
|
16416
|
+
execSync19(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { stdio: "pipe", timeout: 18e4 });
|
|
15995
16417
|
} catch {
|
|
15996
16418
|
renderWarning("Update install failed. Try manually: npm i -g open-agents-ai");
|
|
15997
16419
|
return;
|
|
@@ -16078,9 +16500,9 @@ var init_commands = __esm({
|
|
|
16078
16500
|
});
|
|
16079
16501
|
|
|
16080
16502
|
// packages/cli/dist/tui/project-context.js
|
|
16081
|
-
import { existsSync as
|
|
16082
|
-
import { join as
|
|
16083
|
-
import { execSync as
|
|
16503
|
+
import { existsSync as existsSync18, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "node:fs";
|
|
16504
|
+
import { join as join24, basename as basename8 } from "node:path";
|
|
16505
|
+
import { execSync as execSync16 } from "node:child_process";
|
|
16084
16506
|
import { homedir as homedir9, platform as platform2, release } from "node:os";
|
|
16085
16507
|
function getModelTier(modelName) {
|
|
16086
16508
|
const m = modelName.toLowerCase();
|
|
@@ -16114,10 +16536,10 @@ function loadProjectMap(repoRoot) {
|
|
|
16114
16536
|
if (!hasOaDirectory(repoRoot)) {
|
|
16115
16537
|
initOaDirectory(repoRoot);
|
|
16116
16538
|
}
|
|
16117
|
-
const mapPath =
|
|
16118
|
-
if (
|
|
16539
|
+
const mapPath = join24(repoRoot, OA_DIR, "context", "project-map.md");
|
|
16540
|
+
if (existsSync18(mapPath)) {
|
|
16119
16541
|
try {
|
|
16120
|
-
const content =
|
|
16542
|
+
const content = readFileSync14(mapPath, "utf-8");
|
|
16121
16543
|
return content;
|
|
16122
16544
|
} catch {
|
|
16123
16545
|
}
|
|
@@ -16126,19 +16548,19 @@ function loadProjectMap(repoRoot) {
|
|
|
16126
16548
|
}
|
|
16127
16549
|
function getGitInfo(repoRoot) {
|
|
16128
16550
|
try {
|
|
16129
|
-
|
|
16551
|
+
execSync16("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
16130
16552
|
} catch {
|
|
16131
16553
|
return "";
|
|
16132
16554
|
}
|
|
16133
16555
|
const lines = [];
|
|
16134
16556
|
try {
|
|
16135
|
-
const branch =
|
|
16557
|
+
const branch = execSync16("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
16136
16558
|
if (branch)
|
|
16137
16559
|
lines.push(`Branch: ${branch}`);
|
|
16138
16560
|
} catch {
|
|
16139
16561
|
}
|
|
16140
16562
|
try {
|
|
16141
|
-
const status =
|
|
16563
|
+
const status = execSync16("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
16142
16564
|
if (status) {
|
|
16143
16565
|
const changed = status.split("\n").length;
|
|
16144
16566
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -16148,7 +16570,7 @@ function getGitInfo(repoRoot) {
|
|
|
16148
16570
|
} catch {
|
|
16149
16571
|
}
|
|
16150
16572
|
try {
|
|
16151
|
-
const log =
|
|
16573
|
+
const log = execSync16("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
16152
16574
|
if (log)
|
|
16153
16575
|
lines.push(`Recent commits:
|
|
16154
16576
|
${log}`);
|
|
@@ -16158,33 +16580,33 @@ ${log}`);
|
|
|
16158
16580
|
}
|
|
16159
16581
|
function loadMemoryContext(repoRoot) {
|
|
16160
16582
|
const sections = [];
|
|
16161
|
-
const oaMemDir =
|
|
16583
|
+
const oaMemDir = join24(repoRoot, OA_DIR, "memory");
|
|
16162
16584
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
16163
16585
|
if (oaEntries)
|
|
16164
16586
|
sections.push(oaEntries);
|
|
16165
|
-
const legacyMemDir =
|
|
16166
|
-
if (legacyMemDir !== oaMemDir &&
|
|
16587
|
+
const legacyMemDir = join24(repoRoot, ".open-agents", "memory");
|
|
16588
|
+
if (legacyMemDir !== oaMemDir && existsSync18(legacyMemDir)) {
|
|
16167
16589
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
16168
16590
|
if (legacyEntries)
|
|
16169
16591
|
sections.push(legacyEntries);
|
|
16170
16592
|
}
|
|
16171
|
-
const globalMemDir =
|
|
16593
|
+
const globalMemDir = join24(homedir9(), ".open-agents", "memory");
|
|
16172
16594
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
16173
16595
|
if (globalEntries)
|
|
16174
16596
|
sections.push(globalEntries);
|
|
16175
16597
|
return sections.join("\n\n");
|
|
16176
16598
|
}
|
|
16177
16599
|
function loadMemoryDir(memDir, scope) {
|
|
16178
|
-
if (!
|
|
16600
|
+
if (!existsSync18(memDir))
|
|
16179
16601
|
return "";
|
|
16180
16602
|
const lines = [];
|
|
16181
16603
|
try {
|
|
16182
16604
|
const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
|
|
16183
16605
|
for (const file of files.slice(0, 10)) {
|
|
16184
16606
|
try {
|
|
16185
|
-
const raw =
|
|
16607
|
+
const raw = readFileSync14(join24(memDir, file), "utf-8");
|
|
16186
16608
|
const entries = JSON.parse(raw);
|
|
16187
|
-
const topic =
|
|
16609
|
+
const topic = basename8(file, ".json");
|
|
16188
16610
|
const keys = Object.keys(entries);
|
|
16189
16611
|
if (keys.length === 0)
|
|
16190
16612
|
continue;
|
|
@@ -16208,9 +16630,11 @@ function loadSessionHistory(repoRoot) {
|
|
|
16208
16630
|
return "";
|
|
16209
16631
|
const lines = ["Recent tasks in this project:"];
|
|
16210
16632
|
for (const s of sessions) {
|
|
16633
|
+
if (!s.startedAt || !s.task)
|
|
16634
|
+
continue;
|
|
16211
16635
|
const status = s.completed ? "completed" : "incomplete";
|
|
16212
16636
|
const date = s.startedAt.split("T")[0];
|
|
16213
|
-
lines.push(`- [${date}] ${s.task.slice(0, 80)} (${status}, ${s.turns} turns)`);
|
|
16637
|
+
lines.push(`- [${date}] ${s.task.slice(0, 80)} (${status}, ${s.turns ?? 0} turns)`);
|
|
16214
16638
|
if (s.summary) {
|
|
16215
16639
|
lines.push(` Summary: ${s.summary.slice(0, 120)}`);
|
|
16216
16640
|
}
|
|
@@ -17207,22 +17631,22 @@ var init_carousel = __esm({
|
|
|
17207
17631
|
});
|
|
17208
17632
|
|
|
17209
17633
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
17210
|
-
import { existsSync as
|
|
17211
|
-
import { join as
|
|
17634
|
+
import { existsSync as existsSync19, readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
|
|
17635
|
+
import { join as join25, basename as basename9 } from "node:path";
|
|
17212
17636
|
function loadToolProfile(repoRoot) {
|
|
17213
|
-
const filePath =
|
|
17637
|
+
const filePath = join25(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
17214
17638
|
try {
|
|
17215
|
-
if (!
|
|
17639
|
+
if (!existsSync19(filePath))
|
|
17216
17640
|
return null;
|
|
17217
|
-
return JSON.parse(
|
|
17641
|
+
return JSON.parse(readFileSync15(filePath, "utf-8"));
|
|
17218
17642
|
} catch {
|
|
17219
17643
|
return null;
|
|
17220
17644
|
}
|
|
17221
17645
|
}
|
|
17222
17646
|
function saveToolProfile(repoRoot, profile) {
|
|
17223
|
-
const contextDir =
|
|
17647
|
+
const contextDir = join25(repoRoot, OA_DIR, "context");
|
|
17224
17648
|
mkdirSync8(contextDir, { recursive: true });
|
|
17225
|
-
writeFileSync8(
|
|
17649
|
+
writeFileSync8(join25(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
17226
17650
|
}
|
|
17227
17651
|
function categorizeToolCall(toolName) {
|
|
17228
17652
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -17280,25 +17704,25 @@ function weightedColor(profile) {
|
|
|
17280
17704
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
17281
17705
|
}
|
|
17282
17706
|
function loadCachedDescriptors(repoRoot) {
|
|
17283
|
-
const filePath =
|
|
17707
|
+
const filePath = join25(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
17284
17708
|
try {
|
|
17285
|
-
if (!
|
|
17709
|
+
if (!existsSync19(filePath))
|
|
17286
17710
|
return null;
|
|
17287
|
-
const cached = JSON.parse(
|
|
17711
|
+
const cached = JSON.parse(readFileSync15(filePath, "utf-8"));
|
|
17288
17712
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
17289
17713
|
} catch {
|
|
17290
17714
|
return null;
|
|
17291
17715
|
}
|
|
17292
17716
|
}
|
|
17293
17717
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
17294
|
-
const contextDir =
|
|
17718
|
+
const contextDir = join25(repoRoot, OA_DIR, "context");
|
|
17295
17719
|
mkdirSync8(contextDir, { recursive: true });
|
|
17296
17720
|
const cached = {
|
|
17297
17721
|
phrases,
|
|
17298
17722
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17299
17723
|
sourceHash
|
|
17300
17724
|
};
|
|
17301
|
-
writeFileSync8(
|
|
17725
|
+
writeFileSync8(join25(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
17302
17726
|
}
|
|
17303
17727
|
function generateDescriptors(repoRoot) {
|
|
17304
17728
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -17309,7 +17733,7 @@ function generateDescriptors(repoRoot) {
|
|
|
17309
17733
|
extractFromSessions(repoRoot, tags);
|
|
17310
17734
|
extractFromMemory(repoRoot, tags);
|
|
17311
17735
|
extractFromToolProfile(profile, tags);
|
|
17312
|
-
const repoName2 =
|
|
17736
|
+
const repoName2 = basename9(repoRoot);
|
|
17313
17737
|
if (repoName2 && !tags.includes(repoName2)) {
|
|
17314
17738
|
tags.push(repoName2);
|
|
17315
17739
|
}
|
|
@@ -17346,11 +17770,11 @@ function generateDescriptors(repoRoot) {
|
|
|
17346
17770
|
return phrases;
|
|
17347
17771
|
}
|
|
17348
17772
|
function extractFromPackageJson(repoRoot, tags) {
|
|
17349
|
-
const pkgPath =
|
|
17773
|
+
const pkgPath = join25(repoRoot, "package.json");
|
|
17350
17774
|
try {
|
|
17351
|
-
if (!
|
|
17775
|
+
if (!existsSync19(pkgPath))
|
|
17352
17776
|
return;
|
|
17353
|
-
const pkg = JSON.parse(
|
|
17777
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
17354
17778
|
if (pkg.name && typeof pkg.name === "string") {
|
|
17355
17779
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
17356
17780
|
for (const p of parts)
|
|
@@ -17394,7 +17818,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
17394
17818
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
17395
17819
|
];
|
|
17396
17820
|
for (const check of manifestChecks) {
|
|
17397
|
-
if (
|
|
17821
|
+
if (existsSync19(join25(repoRoot, check.file))) {
|
|
17398
17822
|
tags.push(check.tag);
|
|
17399
17823
|
}
|
|
17400
17824
|
}
|
|
@@ -17416,16 +17840,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
17416
17840
|
}
|
|
17417
17841
|
}
|
|
17418
17842
|
function extractFromMemory(repoRoot, tags) {
|
|
17419
|
-
const memoryDir =
|
|
17843
|
+
const memoryDir = join25(repoRoot, OA_DIR, "memory");
|
|
17420
17844
|
try {
|
|
17421
|
-
if (!
|
|
17845
|
+
if (!existsSync19(memoryDir))
|
|
17422
17846
|
return;
|
|
17423
17847
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
17424
17848
|
for (const file of files) {
|
|
17425
17849
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
17426
17850
|
tags.push(topic);
|
|
17427
17851
|
try {
|
|
17428
|
-
const data = JSON.parse(
|
|
17852
|
+
const data = JSON.parse(readFileSync15(join25(memoryDir, file), "utf-8"));
|
|
17429
17853
|
if (data && typeof data === "object") {
|
|
17430
17854
|
const keys = Object.keys(data).slice(0, 3);
|
|
17431
17855
|
for (const key of keys) {
|
|
@@ -17560,25 +17984,25 @@ var init_carousel_descriptors = __esm({
|
|
|
17560
17984
|
});
|
|
17561
17985
|
|
|
17562
17986
|
// packages/cli/dist/tui/voice.js
|
|
17563
|
-
import { existsSync as
|
|
17564
|
-
import { join as
|
|
17565
|
-
import { homedir as homedir10, tmpdir as
|
|
17566
|
-
import { execSync as
|
|
17987
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync4 } from "node:fs";
|
|
17988
|
+
import { join as join26 } from "node:path";
|
|
17989
|
+
import { homedir as homedir10, tmpdir as tmpdir5, platform as platform3 } from "node:os";
|
|
17990
|
+
import { execSync as execSync17, spawn as nodeSpawn } from "node:child_process";
|
|
17567
17991
|
import { createRequire } from "node:module";
|
|
17568
17992
|
function voiceDir() {
|
|
17569
|
-
return
|
|
17993
|
+
return join26(homedir10(), ".open-agents", "voice");
|
|
17570
17994
|
}
|
|
17571
17995
|
function modelsDir() {
|
|
17572
|
-
return
|
|
17996
|
+
return join26(voiceDir(), "models");
|
|
17573
17997
|
}
|
|
17574
17998
|
function modelDir(id) {
|
|
17575
|
-
return
|
|
17999
|
+
return join26(modelsDir(), id);
|
|
17576
18000
|
}
|
|
17577
18001
|
function modelOnnxPath(id) {
|
|
17578
|
-
return
|
|
18002
|
+
return join26(modelDir(id), "model.onnx");
|
|
17579
18003
|
}
|
|
17580
18004
|
function modelConfigPath(id) {
|
|
17581
|
-
return
|
|
18005
|
+
return join26(modelDir(id), "config.json");
|
|
17582
18006
|
}
|
|
17583
18007
|
function describeToolCall(toolName, args) {
|
|
17584
18008
|
const path = args["path"];
|
|
@@ -17851,11 +18275,11 @@ var init_voice = __esm({
|
|
|
17851
18275
|
const audioData = result["output"].data;
|
|
17852
18276
|
if (audioData.length === 0)
|
|
17853
18277
|
return;
|
|
17854
|
-
const wavPath =
|
|
18278
|
+
const wavPath = join26(tmpdir5(), `oa-voice-${Date.now()}.wav`);
|
|
17855
18279
|
this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
|
|
17856
18280
|
await this.playWav(wavPath);
|
|
17857
18281
|
try {
|
|
17858
|
-
|
|
18282
|
+
unlinkSync4(wavPath);
|
|
17859
18283
|
} catch {
|
|
17860
18284
|
}
|
|
17861
18285
|
}
|
|
@@ -17940,7 +18364,7 @@ var init_voice = __esm({
|
|
|
17940
18364
|
const cmd = this.getPlayCommand(path);
|
|
17941
18365
|
if (!cmd)
|
|
17942
18366
|
return;
|
|
17943
|
-
return new Promise((
|
|
18367
|
+
return new Promise((resolve21) => {
|
|
17944
18368
|
const child = nodeSpawn(cmd[0], cmd.slice(1), {
|
|
17945
18369
|
stdio: "ignore",
|
|
17946
18370
|
detached: false
|
|
@@ -17949,12 +18373,12 @@ var init_voice = __esm({
|
|
|
17949
18373
|
child.on("close", () => {
|
|
17950
18374
|
if (this.currentPlayback === child)
|
|
17951
18375
|
this.currentPlayback = null;
|
|
17952
|
-
|
|
18376
|
+
resolve21();
|
|
17953
18377
|
});
|
|
17954
18378
|
child.on("error", () => {
|
|
17955
18379
|
if (this.currentPlayback === child)
|
|
17956
18380
|
this.currentPlayback = null;
|
|
17957
|
-
|
|
18381
|
+
resolve21();
|
|
17958
18382
|
});
|
|
17959
18383
|
setTimeout(() => {
|
|
17960
18384
|
if (this.currentPlayback === child) {
|
|
@@ -17964,7 +18388,7 @@ var init_voice = __esm({
|
|
|
17964
18388
|
}
|
|
17965
18389
|
this.currentPlayback = null;
|
|
17966
18390
|
}
|
|
17967
|
-
|
|
18391
|
+
resolve21();
|
|
17968
18392
|
}, 15e3);
|
|
17969
18393
|
});
|
|
17970
18394
|
}
|
|
@@ -17981,7 +18405,7 @@ var init_voice = __esm({
|
|
|
17981
18405
|
}
|
|
17982
18406
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
17983
18407
|
try {
|
|
17984
|
-
|
|
18408
|
+
execSync17(`which ${player}`, { stdio: "pipe" });
|
|
17985
18409
|
return [player, path];
|
|
17986
18410
|
} catch {
|
|
17987
18411
|
}
|
|
@@ -18006,14 +18430,14 @@ var init_voice = __esm({
|
|
|
18006
18430
|
const arch = process.arch;
|
|
18007
18431
|
const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
|
|
18008
18432
|
mkdirSync9(voiceDir(), { recursive: true });
|
|
18009
|
-
const pkgPath =
|
|
18433
|
+
const pkgPath = join26(voiceDir(), "package.json");
|
|
18010
18434
|
const expectedDeps = {
|
|
18011
18435
|
"onnxruntime-node": "^1.21.0",
|
|
18012
18436
|
"phonemizer": "^1.2.1"
|
|
18013
18437
|
};
|
|
18014
|
-
if (
|
|
18438
|
+
if (existsSync20(pkgPath)) {
|
|
18015
18439
|
try {
|
|
18016
|
-
const existing = JSON.parse(
|
|
18440
|
+
const existing = JSON.parse(readFileSync16(pkgPath, "utf8"));
|
|
18017
18441
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
18018
18442
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
18019
18443
|
writeFileSync9(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -18021,14 +18445,14 @@ var init_voice = __esm({
|
|
|
18021
18445
|
} catch {
|
|
18022
18446
|
}
|
|
18023
18447
|
}
|
|
18024
|
-
if (!
|
|
18448
|
+
if (!existsSync20(pkgPath)) {
|
|
18025
18449
|
writeFileSync9(pkgPath, JSON.stringify({
|
|
18026
18450
|
name: "open-agents-voice",
|
|
18027
18451
|
private: true,
|
|
18028
18452
|
dependencies: expectedDeps
|
|
18029
18453
|
}, null, 2));
|
|
18030
18454
|
}
|
|
18031
|
-
const voiceRequire = createRequire(
|
|
18455
|
+
const voiceRequire = createRequire(join26(voiceDir(), "index.js"));
|
|
18032
18456
|
try {
|
|
18033
18457
|
this.ort = voiceRequire("onnxruntime-node");
|
|
18034
18458
|
} catch {
|
|
@@ -18037,7 +18461,7 @@ var init_voice = __esm({
|
|
|
18037
18461
|
}
|
|
18038
18462
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
18039
18463
|
try {
|
|
18040
|
-
|
|
18464
|
+
execSync17("npm install --no-audit --no-fund", {
|
|
18041
18465
|
cwd: voiceDir(),
|
|
18042
18466
|
stdio: "pipe",
|
|
18043
18467
|
timeout: 12e4
|
|
@@ -18058,7 +18482,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18058
18482
|
}
|
|
18059
18483
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
18060
18484
|
try {
|
|
18061
|
-
|
|
18485
|
+
execSync17("npm install --no-audit --no-fund", {
|
|
18062
18486
|
cwd: voiceDir(),
|
|
18063
18487
|
stdio: "pipe",
|
|
18064
18488
|
timeout: 12e4
|
|
@@ -18082,10 +18506,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18082
18506
|
const dir = modelDir(id);
|
|
18083
18507
|
const onnxPath = modelOnnxPath(id);
|
|
18084
18508
|
const configPath = modelConfigPath(id);
|
|
18085
|
-
if (
|
|
18509
|
+
if (existsSync20(onnxPath) && existsSync20(configPath))
|
|
18086
18510
|
return;
|
|
18087
18511
|
mkdirSync9(dir, { recursive: true });
|
|
18088
|
-
if (!
|
|
18512
|
+
if (!existsSync20(configPath)) {
|
|
18089
18513
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
18090
18514
|
const configResp = await fetch(model.configUrl);
|
|
18091
18515
|
if (!configResp.ok)
|
|
@@ -18093,7 +18517,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18093
18517
|
const configText = await configResp.text();
|
|
18094
18518
|
writeFileSync9(configPath, configText);
|
|
18095
18519
|
}
|
|
18096
|
-
if (!
|
|
18520
|
+
if (!existsSync20(onnxPath)) {
|
|
18097
18521
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
18098
18522
|
const onnxResp = await fetch(model.onnxUrl);
|
|
18099
18523
|
if (!onnxResp.ok)
|
|
@@ -18129,10 +18553,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18129
18553
|
throw new Error("ONNX runtime not loaded");
|
|
18130
18554
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
18131
18555
|
const configPath = modelConfigPath(this.modelId);
|
|
18132
|
-
if (!
|
|
18556
|
+
if (!existsSync20(onnxPath) || !existsSync20(configPath)) {
|
|
18133
18557
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
18134
18558
|
}
|
|
18135
|
-
this.config = JSON.parse(
|
|
18559
|
+
this.config = JSON.parse(readFileSync16(configPath, "utf8"));
|
|
18136
18560
|
renderInfo("Loading voice model...");
|
|
18137
18561
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
18138
18562
|
executionProviders: ["cpu"],
|
|
@@ -18633,10 +19057,10 @@ var init_stream_renderer = __esm({
|
|
|
18633
19057
|
|
|
18634
19058
|
// packages/cli/dist/tui/edit-history.js
|
|
18635
19059
|
import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
|
|
18636
|
-
import { join as
|
|
19060
|
+
import { join as join27 } from "node:path";
|
|
18637
19061
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
18638
|
-
const historyDir =
|
|
18639
|
-
const logPath =
|
|
19062
|
+
const historyDir = join27(repoRoot, ".oa", "history");
|
|
19063
|
+
const logPath = join27(historyDir, "edits.jsonl");
|
|
18640
19064
|
try {
|
|
18641
19065
|
mkdirSync10(historyDir, { recursive: true });
|
|
18642
19066
|
} catch {
|
|
@@ -18747,9 +19171,9 @@ var init_edit_history = __esm({
|
|
|
18747
19171
|
});
|
|
18748
19172
|
|
|
18749
19173
|
// packages/cli/dist/tui/dream-engine.js
|
|
18750
|
-
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as
|
|
18751
|
-
import { join as
|
|
18752
|
-
import { execSync as
|
|
19174
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync17, existsSync as existsSync21, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
19175
|
+
import { join as join28, basename as basename10 } from "node:path";
|
|
19176
|
+
import { execSync as execSync18 } from "node:child_process";
|
|
18753
19177
|
function adaptTool(tool) {
|
|
18754
19178
|
return {
|
|
18755
19179
|
name: tool.name,
|
|
@@ -18923,12 +19347,12 @@ var init_dream_engine = __esm({
|
|
|
18923
19347
|
const content = String(args["content"] ?? "");
|
|
18924
19348
|
if (!rawPath)
|
|
18925
19349
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
18926
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
19350
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
|
|
18927
19351
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
18928
19352
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
18929
19353
|
}
|
|
18930
19354
|
try {
|
|
18931
|
-
const dir =
|
|
19355
|
+
const dir = join28(targetPath, "..");
|
|
18932
19356
|
mkdirSync11(dir, { recursive: true });
|
|
18933
19357
|
writeFileSync10(targetPath, content, "utf-8");
|
|
18934
19358
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -18958,15 +19382,15 @@ var init_dream_engine = __esm({
|
|
|
18958
19382
|
const rawPath = String(args["path"] ?? "");
|
|
18959
19383
|
const oldStr = String(args["old_string"] ?? "");
|
|
18960
19384
|
const newStr = String(args["new_string"] ?? "");
|
|
18961
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
19385
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
|
|
18962
19386
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
18963
19387
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
18964
19388
|
}
|
|
18965
19389
|
try {
|
|
18966
|
-
if (!
|
|
19390
|
+
if (!existsSync21(targetPath)) {
|
|
18967
19391
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
18968
19392
|
}
|
|
18969
|
-
let content =
|
|
19393
|
+
let content = readFileSync17(targetPath, "utf-8");
|
|
18970
19394
|
if (!content.includes(oldStr)) {
|
|
18971
19395
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
18972
19396
|
}
|
|
@@ -19002,7 +19426,7 @@ var init_dream_engine = __esm({
|
|
|
19002
19426
|
}
|
|
19003
19427
|
}
|
|
19004
19428
|
try {
|
|
19005
|
-
const output =
|
|
19429
|
+
const output = execSync18(cmd, {
|
|
19006
19430
|
cwd: this.repoRoot,
|
|
19007
19431
|
timeout: 3e4,
|
|
19008
19432
|
encoding: "utf-8",
|
|
@@ -19025,7 +19449,7 @@ var init_dream_engine = __esm({
|
|
|
19025
19449
|
constructor(config, repoRoot) {
|
|
19026
19450
|
this.config = config;
|
|
19027
19451
|
this.repoRoot = repoRoot;
|
|
19028
|
-
this.dreamsDir =
|
|
19452
|
+
this.dreamsDir = join28(repoRoot, ".oa", "dreams");
|
|
19029
19453
|
this.state = {
|
|
19030
19454
|
mode: "default",
|
|
19031
19455
|
active: false,
|
|
@@ -19097,7 +19521,7 @@ ${result.summary}`;
|
|
|
19097
19521
|
if (mode !== "default" || cycle === totalCycles) {
|
|
19098
19522
|
renderDreamContraction(cycle);
|
|
19099
19523
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
19100
|
-
const summaryPath =
|
|
19524
|
+
const summaryPath = join28(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
19101
19525
|
writeFileSync10(summaryPath, cycleSummary, "utf-8");
|
|
19102
19526
|
}
|
|
19103
19527
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -19220,29 +19644,29 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
19220
19644
|
}
|
|
19221
19645
|
/** Save workspace backup for lucid mode */
|
|
19222
19646
|
saveVersionCheckpoint(cycle) {
|
|
19223
|
-
const checkpointDir =
|
|
19647
|
+
const checkpointDir = join28(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
19224
19648
|
try {
|
|
19225
19649
|
mkdirSync11(checkpointDir, { recursive: true });
|
|
19226
19650
|
try {
|
|
19227
|
-
const gitStatus =
|
|
19651
|
+
const gitStatus = execSync18("git status --porcelain", {
|
|
19228
19652
|
cwd: this.repoRoot,
|
|
19229
19653
|
encoding: "utf-8",
|
|
19230
19654
|
timeout: 1e4
|
|
19231
19655
|
});
|
|
19232
|
-
const gitDiff =
|
|
19656
|
+
const gitDiff = execSync18("git diff", {
|
|
19233
19657
|
cwd: this.repoRoot,
|
|
19234
19658
|
encoding: "utf-8",
|
|
19235
19659
|
timeout: 1e4
|
|
19236
19660
|
});
|
|
19237
|
-
const gitHash =
|
|
19661
|
+
const gitHash = execSync18("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
19238
19662
|
cwd: this.repoRoot,
|
|
19239
19663
|
encoding: "utf-8",
|
|
19240
19664
|
timeout: 5e3
|
|
19241
19665
|
}).trim();
|
|
19242
|
-
writeFileSync10(
|
|
19243
|
-
writeFileSync10(
|
|
19244
|
-
writeFileSync10(
|
|
19245
|
-
writeFileSync10(
|
|
19666
|
+
writeFileSync10(join28(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
19667
|
+
writeFileSync10(join28(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
19668
|
+
writeFileSync10(join28(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
19669
|
+
writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
19246
19670
|
cycle,
|
|
19247
19671
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19248
19672
|
gitHash,
|
|
@@ -19250,7 +19674,7 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
19250
19674
|
}, null, 2), "utf-8");
|
|
19251
19675
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
19252
19676
|
} catch {
|
|
19253
|
-
writeFileSync10(
|
|
19677
|
+
writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
19254
19678
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
19255
19679
|
}
|
|
19256
19680
|
} catch (err) {
|
|
@@ -19308,14 +19732,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
19308
19732
|
---
|
|
19309
19733
|
*Auto-generated by open-agents dream engine*
|
|
19310
19734
|
`;
|
|
19311
|
-
writeFileSync10(
|
|
19735
|
+
writeFileSync10(join28(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
19312
19736
|
} catch {
|
|
19313
19737
|
}
|
|
19314
19738
|
}
|
|
19315
19739
|
/** Save dream state for resume/inspection */
|
|
19316
19740
|
saveDreamState() {
|
|
19317
19741
|
try {
|
|
19318
|
-
writeFileSync10(
|
|
19742
|
+
writeFileSync10(join28(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
19319
19743
|
} catch {
|
|
19320
19744
|
}
|
|
19321
19745
|
}
|
|
@@ -20147,22 +20571,22 @@ var init_status_bar = __esm({
|
|
|
20147
20571
|
import * as readline2 from "node:readline";
|
|
20148
20572
|
import { Writable } from "node:stream";
|
|
20149
20573
|
import { cwd } from "node:process";
|
|
20150
|
-
import { resolve as
|
|
20574
|
+
import { resolve as resolve18, join as join29, dirname as dirname8, extname as extname9 } from "node:path";
|
|
20151
20575
|
import { createRequire as createRequire2 } from "node:module";
|
|
20152
20576
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
20153
|
-
import { readFileSync as
|
|
20154
|
-
import { existsSync as
|
|
20577
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
20578
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
20155
20579
|
function getVersion() {
|
|
20156
20580
|
try {
|
|
20157
20581
|
const require2 = createRequire2(import.meta.url);
|
|
20158
20582
|
const thisDir = dirname8(fileURLToPath5(import.meta.url));
|
|
20159
20583
|
const candidates = [
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
20584
|
+
join29(thisDir, "..", "package.json"),
|
|
20585
|
+
join29(thisDir, "..", "..", "package.json"),
|
|
20586
|
+
join29(thisDir, "..", "..", "..", "package.json")
|
|
20163
20587
|
];
|
|
20164
20588
|
for (const pkgPath of candidates) {
|
|
20165
|
-
if (
|
|
20589
|
+
if (existsSync22(pkgPath)) {
|
|
20166
20590
|
const pkg = require2(pkgPath);
|
|
20167
20591
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
20168
20592
|
return pkg.version ?? "0.0.0";
|
|
@@ -20252,7 +20676,10 @@ function buildTools(repoRoot, config) {
|
|
|
20252
20676
|
// Vision tools (Moondream — desktop awareness + point-and-click)
|
|
20253
20677
|
new VisionTool(repoRoot),
|
|
20254
20678
|
new DesktopClickTool(repoRoot),
|
|
20255
|
-
new DesktopDescribeTool(repoRoot)
|
|
20679
|
+
new DesktopDescribeTool(repoRoot),
|
|
20680
|
+
// PDF tools (OCR + text extraction)
|
|
20681
|
+
new OcrPdfTool(repoRoot),
|
|
20682
|
+
new PdfToTextTool(repoRoot)
|
|
20256
20683
|
];
|
|
20257
20684
|
return [
|
|
20258
20685
|
...executionTools.map(adaptTool2),
|
|
@@ -20556,7 +20983,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
20556
20983
|
} };
|
|
20557
20984
|
}
|
|
20558
20985
|
async function startInteractive(config, repoPath) {
|
|
20559
|
-
const repoRoot =
|
|
20986
|
+
const repoRoot = resolve18(repoPath ?? cwd());
|
|
20560
20987
|
const resumeFlag = process.env.__OA_RESUMED ?? "";
|
|
20561
20988
|
const isResumed = resumeFlag !== "";
|
|
20562
20989
|
const hasTaskToResume = resumeFlag === "1";
|
|
@@ -20708,14 +21135,14 @@ async function startInteractive(config, repoPath) {
|
|
|
20708
21135
|
renderInfo(msg);
|
|
20709
21136
|
statusBar.endContentWrite();
|
|
20710
21137
|
}
|
|
20711
|
-
}, () => new Promise((
|
|
21138
|
+
}, () => new Promise((resolve21) => {
|
|
20712
21139
|
depSudoPromptPending = true;
|
|
20713
21140
|
depSudoResolver = (pw) => {
|
|
20714
21141
|
depSudoPromptPending = false;
|
|
20715
21142
|
depSudoResolver = null;
|
|
20716
21143
|
if (pw)
|
|
20717
21144
|
sessionSudoPassword = pw;
|
|
20718
|
-
|
|
21145
|
+
resolve21(pw);
|
|
20719
21146
|
};
|
|
20720
21147
|
if (statusBar?.isActive) {
|
|
20721
21148
|
statusBar.beginContentWrite();
|
|
@@ -21227,13 +21654,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
21227
21654
|
}
|
|
21228
21655
|
}
|
|
21229
21656
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
21230
|
-
const isImage = isImagePath(cleanPath) &&
|
|
21231
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
21657
|
+
const isImage = isImagePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
|
|
21658
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
|
|
21232
21659
|
if (activeTask) {
|
|
21233
21660
|
if (isImage) {
|
|
21234
21661
|
try {
|
|
21235
|
-
const imgPath =
|
|
21236
|
-
const imgBuffer =
|
|
21662
|
+
const imgPath = resolve18(repoRoot, cleanPath);
|
|
21663
|
+
const imgBuffer = readFileSync18(imgPath);
|
|
21237
21664
|
const base64 = imgBuffer.toString("base64");
|
|
21238
21665
|
const ext = extname9(cleanPath).toLowerCase();
|
|
21239
21666
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -21246,7 +21673,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
21246
21673
|
} else if (isMedia) {
|
|
21247
21674
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
21248
21675
|
const engine = getListenEngine();
|
|
21249
|
-
const result = await engine.transcribeFile(
|
|
21676
|
+
const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
|
|
21250
21677
|
if (result) {
|
|
21251
21678
|
const transcript = `[Transcription of ${cleanPath}]
|
|
21252
21679
|
${result.text}`;
|
|
@@ -21279,7 +21706,7 @@ ${result.text}`;
|
|
|
21279
21706
|
if (isMedia && fullInput === input) {
|
|
21280
21707
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
21281
21708
|
const engine = getListenEngine();
|
|
21282
|
-
const result = await engine.transcribeFile(
|
|
21709
|
+
const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
|
|
21283
21710
|
if (result) {
|
|
21284
21711
|
fullInput = `The user has provided an audio/video file: ${cleanPath}.
|
|
21285
21712
|
|
|
@@ -21399,7 +21826,7 @@ ${c2.dim("(Use /quit to exit)")}
|
|
|
21399
21826
|
});
|
|
21400
21827
|
}
|
|
21401
21828
|
async function runWithTUI(task, config, repoPath) {
|
|
21402
|
-
const repoRoot =
|
|
21829
|
+
const repoRoot = resolve18(repoPath ?? cwd());
|
|
21403
21830
|
const needsSetup = isFirstRun() || !await isModelAvailable(config);
|
|
21404
21831
|
if (needsSetup && config.backendType === "ollama") {
|
|
21405
21832
|
const setupModel = await runSetupWizard(config);
|
|
@@ -21504,7 +21931,7 @@ import { glob } from "glob";
|
|
|
21504
21931
|
import ignore from "ignore";
|
|
21505
21932
|
import { readFile as readFile10, stat as stat4 } from "node:fs/promises";
|
|
21506
21933
|
import { createHash } from "node:crypto";
|
|
21507
|
-
import { join as
|
|
21934
|
+
import { join as join30, relative as relative3, extname as extname10, basename as basename11 } from "node:path";
|
|
21508
21935
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
21509
21936
|
var init_codebase_indexer = __esm({
|
|
21510
21937
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -21548,7 +21975,7 @@ var init_codebase_indexer = __esm({
|
|
|
21548
21975
|
const ig = ignore.default();
|
|
21549
21976
|
if (this.config.respectGitignore) {
|
|
21550
21977
|
try {
|
|
21551
|
-
const gitignoreContent = await readFile10(
|
|
21978
|
+
const gitignoreContent = await readFile10(join30(this.config.rootDir, ".gitignore"), "utf-8");
|
|
21552
21979
|
ig.add(gitignoreContent);
|
|
21553
21980
|
} catch {
|
|
21554
21981
|
}
|
|
@@ -21563,7 +21990,7 @@ var init_codebase_indexer = __esm({
|
|
|
21563
21990
|
for (const relativePath of files) {
|
|
21564
21991
|
if (ig.ignores(relativePath))
|
|
21565
21992
|
continue;
|
|
21566
|
-
const fullPath =
|
|
21993
|
+
const fullPath = join30(this.config.rootDir, relativePath);
|
|
21567
21994
|
try {
|
|
21568
21995
|
const fileStat = await stat4(fullPath);
|
|
21569
21996
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -21586,7 +22013,7 @@ var init_codebase_indexer = __esm({
|
|
|
21586
22013
|
}
|
|
21587
22014
|
buildTree(files) {
|
|
21588
22015
|
const root = {
|
|
21589
|
-
name:
|
|
22016
|
+
name: basename11(this.config.rootDir),
|
|
21590
22017
|
path: this.config.rootDir,
|
|
21591
22018
|
type: "directory",
|
|
21592
22019
|
children: []
|
|
@@ -21609,7 +22036,7 @@ var init_codebase_indexer = __esm({
|
|
|
21609
22036
|
if (!child) {
|
|
21610
22037
|
child = {
|
|
21611
22038
|
name: part,
|
|
21612
|
-
path:
|
|
22039
|
+
path: join30(current.path, part),
|
|
21613
22040
|
type: "directory",
|
|
21614
22041
|
children: []
|
|
21615
22042
|
};
|
|
@@ -21683,18 +22110,18 @@ var index_repo_exports = {};
|
|
|
21683
22110
|
__export(index_repo_exports, {
|
|
21684
22111
|
indexRepoCommand: () => indexRepoCommand
|
|
21685
22112
|
});
|
|
21686
|
-
import { resolve as
|
|
21687
|
-
import { existsSync as
|
|
22113
|
+
import { resolve as resolve19 } from "node:path";
|
|
22114
|
+
import { existsSync as existsSync23, statSync as statSync9 } from "node:fs";
|
|
21688
22115
|
import { cwd as cwd2 } from "node:process";
|
|
21689
22116
|
async function indexRepoCommand(opts, _config) {
|
|
21690
|
-
const repoRoot =
|
|
22117
|
+
const repoRoot = resolve19(opts.repoPath ?? cwd2());
|
|
21691
22118
|
printHeader("Index Repository");
|
|
21692
22119
|
printInfo(`Indexing: ${repoRoot}`);
|
|
21693
|
-
if (!
|
|
22120
|
+
if (!existsSync23(repoRoot)) {
|
|
21694
22121
|
printError(`Path does not exist: ${repoRoot}`);
|
|
21695
22122
|
process.exit(1);
|
|
21696
22123
|
}
|
|
21697
|
-
const stat5 =
|
|
22124
|
+
const stat5 = statSync9(repoRoot);
|
|
21698
22125
|
if (!stat5.isDirectory()) {
|
|
21699
22126
|
printError(`Path is not a directory: ${repoRoot}`);
|
|
21700
22127
|
process.exit(1);
|
|
@@ -21936,7 +22363,7 @@ var config_exports = {};
|
|
|
21936
22363
|
__export(config_exports, {
|
|
21937
22364
|
configCommand: () => configCommand
|
|
21938
22365
|
});
|
|
21939
|
-
import { join as
|
|
22366
|
+
import { join as join31, resolve as resolve20 } from "node:path";
|
|
21940
22367
|
import { homedir as homedir11 } from "node:os";
|
|
21941
22368
|
import { cwd as cwd3 } from "node:process";
|
|
21942
22369
|
function coerceForSettings(key, value) {
|
|
@@ -21957,7 +22384,7 @@ async function configCommand(opts, config) {
|
|
|
21957
22384
|
return handleShow(opts, config);
|
|
21958
22385
|
}
|
|
21959
22386
|
function handleShow(opts, config) {
|
|
21960
|
-
const repoRoot =
|
|
22387
|
+
const repoRoot = resolve20(opts.repoPath ?? cwd3());
|
|
21961
22388
|
printHeader("Configuration");
|
|
21962
22389
|
printSection("Active Settings (merged)");
|
|
21963
22390
|
printKeyValue("backendUrl", config.backendUrl, 2);
|
|
@@ -21989,7 +22416,7 @@ function handleShow(opts, config) {
|
|
|
21989
22416
|
}
|
|
21990
22417
|
}
|
|
21991
22418
|
printSection("Config File");
|
|
21992
|
-
printInfo(`~/.open-agents/config.json (${
|
|
22419
|
+
printInfo(`~/.open-agents/config.json (${join31(homedir11(), ".open-agents", "config.json")})`);
|
|
21993
22420
|
printSection("Priority Chain");
|
|
21994
22421
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
21995
22422
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -22022,13 +22449,13 @@ function handleSet(opts, _config) {
|
|
|
22022
22449
|
process.exit(1);
|
|
22023
22450
|
}
|
|
22024
22451
|
if (opts.local) {
|
|
22025
|
-
const repoRoot =
|
|
22452
|
+
const repoRoot = resolve20(opts.repoPath ?? cwd3());
|
|
22026
22453
|
try {
|
|
22027
22454
|
initOaDirectory(repoRoot);
|
|
22028
22455
|
const coerced = coerceForSettings(key, value);
|
|
22029
22456
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
22030
22457
|
printSuccess(`Project override set: ${key} = ${value}`);
|
|
22031
|
-
printInfo(`Saved to ${
|
|
22458
|
+
printInfo(`Saved to ${join31(repoRoot, ".oa", "settings.json")}`);
|
|
22032
22459
|
printInfo("This override applies only when running in this workspace.");
|
|
22033
22460
|
} catch (err) {
|
|
22034
22461
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -22180,7 +22607,7 @@ async function serveVllm(opts, config) {
|
|
|
22180
22607
|
await runVllmServer(args, opts.verbose ?? false);
|
|
22181
22608
|
}
|
|
22182
22609
|
async function runVllmServer(args, verbose) {
|
|
22183
|
-
return new Promise((
|
|
22610
|
+
return new Promise((resolve21, reject) => {
|
|
22184
22611
|
const child = spawn9("python", args, {
|
|
22185
22612
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
22186
22613
|
env: { ...process.env }
|
|
@@ -22215,10 +22642,10 @@ async function runVllmServer(args, verbose) {
|
|
|
22215
22642
|
child.once("exit", (code, signal) => {
|
|
22216
22643
|
if (signal) {
|
|
22217
22644
|
printInfo(`vLLM server stopped by signal ${signal}`);
|
|
22218
|
-
|
|
22645
|
+
resolve21();
|
|
22219
22646
|
} else if (code === 0) {
|
|
22220
22647
|
printSuccess("vLLM server exited cleanly");
|
|
22221
|
-
|
|
22648
|
+
resolve21();
|
|
22222
22649
|
} else {
|
|
22223
22650
|
printError(`vLLM server exited with code ${code}`);
|
|
22224
22651
|
reject(new Error(`vLLM exited with code ${code}`));
|
|
@@ -22245,9 +22672,9 @@ var eval_exports = {};
|
|
|
22245
22672
|
__export(eval_exports, {
|
|
22246
22673
|
evalCommand: () => evalCommand
|
|
22247
22674
|
});
|
|
22248
|
-
import { tmpdir as
|
|
22675
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
22249
22676
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
22250
|
-
import { join as
|
|
22677
|
+
import { join as join32 } from "node:path";
|
|
22251
22678
|
async function evalCommand(opts, config) {
|
|
22252
22679
|
const suiteName = opts.suite ?? "basic";
|
|
22253
22680
|
const suite = SUITES[suiteName];
|
|
@@ -22368,9 +22795,9 @@ async function evalCommand(opts, config) {
|
|
|
22368
22795
|
process.exit(failed > 0 ? 1 : 0);
|
|
22369
22796
|
}
|
|
22370
22797
|
function createTempEvalRepo() {
|
|
22371
|
-
const dir =
|
|
22798
|
+
const dir = join32(tmpdir6(), `open-agents-eval-${Date.now()}`);
|
|
22372
22799
|
mkdirSync12(dir, { recursive: true });
|
|
22373
|
-
writeFileSync11(
|
|
22800
|
+
writeFileSync11(join32(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
22374
22801
|
return dir;
|
|
22375
22802
|
}
|
|
22376
22803
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -22430,7 +22857,7 @@ init_updater();
|
|
|
22430
22857
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
22431
22858
|
import { createRequire as createRequire3 } from "node:module";
|
|
22432
22859
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
22433
|
-
import { dirname as dirname9, join as
|
|
22860
|
+
import { dirname as dirname9, join as join33 } from "node:path";
|
|
22434
22861
|
|
|
22435
22862
|
// packages/cli/dist/cli.js
|
|
22436
22863
|
import { createInterface } from "node:readline";
|
|
@@ -22537,7 +22964,7 @@ init_output();
|
|
|
22537
22964
|
function getVersion2() {
|
|
22538
22965
|
try {
|
|
22539
22966
|
const require2 = createRequire3(import.meta.url);
|
|
22540
|
-
const pkgPath =
|
|
22967
|
+
const pkgPath = join33(dirname9(fileURLToPath6(import.meta.url)), "..", "package.json");
|
|
22541
22968
|
const pkg = require2(pkgPath);
|
|
22542
22969
|
return pkg.version;
|
|
22543
22970
|
} catch {
|