open-agents-ai 0.30.7 → 0.30.9
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 +727 -302
- 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 {
|
|
@@ -13403,7 +13742,7 @@ function renderSlashHelp() {
|
|
|
13403
13742
|
["/dream stop", "Wake up \u2014 stop dreaming"],
|
|
13404
13743
|
["/listen", "Toggle live microphone transcription (Whisper)"],
|
|
13405
13744
|
["/listen <model>", "Set model: tiny, base, small, medium, large"],
|
|
13406
|
-
["/listen
|
|
13745
|
+
["/listen manual", "Manual mode \u2014 press Enter to submit (turns off auto)"],
|
|
13407
13746
|
["/listen auto", "Auto-submit after 3s silence (blinking \u25CF indicator)"],
|
|
13408
13747
|
["/listen stop", "Stop listening"],
|
|
13409
13748
|
["/cost", "Show session token cost breakdown"],
|
|
@@ -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,28 +14489,28 @@ ${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
14507
|
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
14169
|
-
const stat5 =
|
|
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
|
}
|
|
@@ -14181,18 +14520,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
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
|
});
|
|
@@ -15693,8 +16115,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
15693
16115
|
renderInfo(msg2);
|
|
15694
16116
|
return "handled";
|
|
15695
16117
|
}
|
|
15696
|
-
if (arg === "confirm") {
|
|
15697
|
-
const msg2 = ctx.listenSetMode?.("confirm") ?? "
|
|
16118
|
+
if (arg === "confirm" || arg === "manual") {
|
|
16119
|
+
const msg2 = ctx.listenSetMode?.("confirm") ?? "Manual mode set.";
|
|
15698
16120
|
renderInfo(msg2);
|
|
15699
16121
|
return "handled";
|
|
15700
16122
|
}
|
|
@@ -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;
|
|
@@ -17209,22 +17631,22 @@ var init_carousel = __esm({
|
|
|
17209
17631
|
});
|
|
17210
17632
|
|
|
17211
17633
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
17212
|
-
import { existsSync as
|
|
17213
|
-
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";
|
|
17214
17636
|
function loadToolProfile(repoRoot) {
|
|
17215
|
-
const filePath =
|
|
17637
|
+
const filePath = join25(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
17216
17638
|
try {
|
|
17217
|
-
if (!
|
|
17639
|
+
if (!existsSync19(filePath))
|
|
17218
17640
|
return null;
|
|
17219
|
-
return JSON.parse(
|
|
17641
|
+
return JSON.parse(readFileSync15(filePath, "utf-8"));
|
|
17220
17642
|
} catch {
|
|
17221
17643
|
return null;
|
|
17222
17644
|
}
|
|
17223
17645
|
}
|
|
17224
17646
|
function saveToolProfile(repoRoot, profile) {
|
|
17225
|
-
const contextDir =
|
|
17647
|
+
const contextDir = join25(repoRoot, OA_DIR, "context");
|
|
17226
17648
|
mkdirSync8(contextDir, { recursive: true });
|
|
17227
|
-
writeFileSync8(
|
|
17649
|
+
writeFileSync8(join25(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
17228
17650
|
}
|
|
17229
17651
|
function categorizeToolCall(toolName) {
|
|
17230
17652
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -17282,25 +17704,25 @@ function weightedColor(profile) {
|
|
|
17282
17704
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
17283
17705
|
}
|
|
17284
17706
|
function loadCachedDescriptors(repoRoot) {
|
|
17285
|
-
const filePath =
|
|
17707
|
+
const filePath = join25(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
17286
17708
|
try {
|
|
17287
|
-
if (!
|
|
17709
|
+
if (!existsSync19(filePath))
|
|
17288
17710
|
return null;
|
|
17289
|
-
const cached = JSON.parse(
|
|
17711
|
+
const cached = JSON.parse(readFileSync15(filePath, "utf-8"));
|
|
17290
17712
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
17291
17713
|
} catch {
|
|
17292
17714
|
return null;
|
|
17293
17715
|
}
|
|
17294
17716
|
}
|
|
17295
17717
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
17296
|
-
const contextDir =
|
|
17718
|
+
const contextDir = join25(repoRoot, OA_DIR, "context");
|
|
17297
17719
|
mkdirSync8(contextDir, { recursive: true });
|
|
17298
17720
|
const cached = {
|
|
17299
17721
|
phrases,
|
|
17300
17722
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17301
17723
|
sourceHash
|
|
17302
17724
|
};
|
|
17303
|
-
writeFileSync8(
|
|
17725
|
+
writeFileSync8(join25(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
17304
17726
|
}
|
|
17305
17727
|
function generateDescriptors(repoRoot) {
|
|
17306
17728
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -17311,7 +17733,7 @@ function generateDescriptors(repoRoot) {
|
|
|
17311
17733
|
extractFromSessions(repoRoot, tags);
|
|
17312
17734
|
extractFromMemory(repoRoot, tags);
|
|
17313
17735
|
extractFromToolProfile(profile, tags);
|
|
17314
|
-
const repoName2 =
|
|
17736
|
+
const repoName2 = basename9(repoRoot);
|
|
17315
17737
|
if (repoName2 && !tags.includes(repoName2)) {
|
|
17316
17738
|
tags.push(repoName2);
|
|
17317
17739
|
}
|
|
@@ -17348,11 +17770,11 @@ function generateDescriptors(repoRoot) {
|
|
|
17348
17770
|
return phrases;
|
|
17349
17771
|
}
|
|
17350
17772
|
function extractFromPackageJson(repoRoot, tags) {
|
|
17351
|
-
const pkgPath =
|
|
17773
|
+
const pkgPath = join25(repoRoot, "package.json");
|
|
17352
17774
|
try {
|
|
17353
|
-
if (!
|
|
17775
|
+
if (!existsSync19(pkgPath))
|
|
17354
17776
|
return;
|
|
17355
|
-
const pkg = JSON.parse(
|
|
17777
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
17356
17778
|
if (pkg.name && typeof pkg.name === "string") {
|
|
17357
17779
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
17358
17780
|
for (const p of parts)
|
|
@@ -17396,7 +17818,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
17396
17818
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
17397
17819
|
];
|
|
17398
17820
|
for (const check of manifestChecks) {
|
|
17399
|
-
if (
|
|
17821
|
+
if (existsSync19(join25(repoRoot, check.file))) {
|
|
17400
17822
|
tags.push(check.tag);
|
|
17401
17823
|
}
|
|
17402
17824
|
}
|
|
@@ -17418,16 +17840,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
17418
17840
|
}
|
|
17419
17841
|
}
|
|
17420
17842
|
function extractFromMemory(repoRoot, tags) {
|
|
17421
|
-
const memoryDir =
|
|
17843
|
+
const memoryDir = join25(repoRoot, OA_DIR, "memory");
|
|
17422
17844
|
try {
|
|
17423
|
-
if (!
|
|
17845
|
+
if (!existsSync19(memoryDir))
|
|
17424
17846
|
return;
|
|
17425
17847
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
17426
17848
|
for (const file of files) {
|
|
17427
17849
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
17428
17850
|
tags.push(topic);
|
|
17429
17851
|
try {
|
|
17430
|
-
const data = JSON.parse(
|
|
17852
|
+
const data = JSON.parse(readFileSync15(join25(memoryDir, file), "utf-8"));
|
|
17431
17853
|
if (data && typeof data === "object") {
|
|
17432
17854
|
const keys = Object.keys(data).slice(0, 3);
|
|
17433
17855
|
for (const key of keys) {
|
|
@@ -17562,25 +17984,25 @@ var init_carousel_descriptors = __esm({
|
|
|
17562
17984
|
});
|
|
17563
17985
|
|
|
17564
17986
|
// packages/cli/dist/tui/voice.js
|
|
17565
|
-
import { existsSync as
|
|
17566
|
-
import { join as
|
|
17567
|
-
import { homedir as homedir10, tmpdir as
|
|
17568
|
-
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";
|
|
17569
17991
|
import { createRequire } from "node:module";
|
|
17570
17992
|
function voiceDir() {
|
|
17571
|
-
return
|
|
17993
|
+
return join26(homedir10(), ".open-agents", "voice");
|
|
17572
17994
|
}
|
|
17573
17995
|
function modelsDir() {
|
|
17574
|
-
return
|
|
17996
|
+
return join26(voiceDir(), "models");
|
|
17575
17997
|
}
|
|
17576
17998
|
function modelDir(id) {
|
|
17577
|
-
return
|
|
17999
|
+
return join26(modelsDir(), id);
|
|
17578
18000
|
}
|
|
17579
18001
|
function modelOnnxPath(id) {
|
|
17580
|
-
return
|
|
18002
|
+
return join26(modelDir(id), "model.onnx");
|
|
17581
18003
|
}
|
|
17582
18004
|
function modelConfigPath(id) {
|
|
17583
|
-
return
|
|
18005
|
+
return join26(modelDir(id), "config.json");
|
|
17584
18006
|
}
|
|
17585
18007
|
function describeToolCall(toolName, args) {
|
|
17586
18008
|
const path = args["path"];
|
|
@@ -17853,11 +18275,11 @@ var init_voice = __esm({
|
|
|
17853
18275
|
const audioData = result["output"].data;
|
|
17854
18276
|
if (audioData.length === 0)
|
|
17855
18277
|
return;
|
|
17856
|
-
const wavPath =
|
|
18278
|
+
const wavPath = join26(tmpdir5(), `oa-voice-${Date.now()}.wav`);
|
|
17857
18279
|
this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
|
|
17858
18280
|
await this.playWav(wavPath);
|
|
17859
18281
|
try {
|
|
17860
|
-
|
|
18282
|
+
unlinkSync4(wavPath);
|
|
17861
18283
|
} catch {
|
|
17862
18284
|
}
|
|
17863
18285
|
}
|
|
@@ -17942,7 +18364,7 @@ var init_voice = __esm({
|
|
|
17942
18364
|
const cmd = this.getPlayCommand(path);
|
|
17943
18365
|
if (!cmd)
|
|
17944
18366
|
return;
|
|
17945
|
-
return new Promise((
|
|
18367
|
+
return new Promise((resolve21) => {
|
|
17946
18368
|
const child = nodeSpawn(cmd[0], cmd.slice(1), {
|
|
17947
18369
|
stdio: "ignore",
|
|
17948
18370
|
detached: false
|
|
@@ -17951,12 +18373,12 @@ var init_voice = __esm({
|
|
|
17951
18373
|
child.on("close", () => {
|
|
17952
18374
|
if (this.currentPlayback === child)
|
|
17953
18375
|
this.currentPlayback = null;
|
|
17954
|
-
|
|
18376
|
+
resolve21();
|
|
17955
18377
|
});
|
|
17956
18378
|
child.on("error", () => {
|
|
17957
18379
|
if (this.currentPlayback === child)
|
|
17958
18380
|
this.currentPlayback = null;
|
|
17959
|
-
|
|
18381
|
+
resolve21();
|
|
17960
18382
|
});
|
|
17961
18383
|
setTimeout(() => {
|
|
17962
18384
|
if (this.currentPlayback === child) {
|
|
@@ -17966,7 +18388,7 @@ var init_voice = __esm({
|
|
|
17966
18388
|
}
|
|
17967
18389
|
this.currentPlayback = null;
|
|
17968
18390
|
}
|
|
17969
|
-
|
|
18391
|
+
resolve21();
|
|
17970
18392
|
}, 15e3);
|
|
17971
18393
|
});
|
|
17972
18394
|
}
|
|
@@ -17983,7 +18405,7 @@ var init_voice = __esm({
|
|
|
17983
18405
|
}
|
|
17984
18406
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
17985
18407
|
try {
|
|
17986
|
-
|
|
18408
|
+
execSync17(`which ${player}`, { stdio: "pipe" });
|
|
17987
18409
|
return [player, path];
|
|
17988
18410
|
} catch {
|
|
17989
18411
|
}
|
|
@@ -18008,14 +18430,14 @@ var init_voice = __esm({
|
|
|
18008
18430
|
const arch = process.arch;
|
|
18009
18431
|
const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
|
|
18010
18432
|
mkdirSync9(voiceDir(), { recursive: true });
|
|
18011
|
-
const pkgPath =
|
|
18433
|
+
const pkgPath = join26(voiceDir(), "package.json");
|
|
18012
18434
|
const expectedDeps = {
|
|
18013
18435
|
"onnxruntime-node": "^1.21.0",
|
|
18014
18436
|
"phonemizer": "^1.2.1"
|
|
18015
18437
|
};
|
|
18016
|
-
if (
|
|
18438
|
+
if (existsSync20(pkgPath)) {
|
|
18017
18439
|
try {
|
|
18018
|
-
const existing = JSON.parse(
|
|
18440
|
+
const existing = JSON.parse(readFileSync16(pkgPath, "utf8"));
|
|
18019
18441
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
18020
18442
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
18021
18443
|
writeFileSync9(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -18023,14 +18445,14 @@ var init_voice = __esm({
|
|
|
18023
18445
|
} catch {
|
|
18024
18446
|
}
|
|
18025
18447
|
}
|
|
18026
|
-
if (!
|
|
18448
|
+
if (!existsSync20(pkgPath)) {
|
|
18027
18449
|
writeFileSync9(pkgPath, JSON.stringify({
|
|
18028
18450
|
name: "open-agents-voice",
|
|
18029
18451
|
private: true,
|
|
18030
18452
|
dependencies: expectedDeps
|
|
18031
18453
|
}, null, 2));
|
|
18032
18454
|
}
|
|
18033
|
-
const voiceRequire = createRequire(
|
|
18455
|
+
const voiceRequire = createRequire(join26(voiceDir(), "index.js"));
|
|
18034
18456
|
try {
|
|
18035
18457
|
this.ort = voiceRequire("onnxruntime-node");
|
|
18036
18458
|
} catch {
|
|
@@ -18039,7 +18461,7 @@ var init_voice = __esm({
|
|
|
18039
18461
|
}
|
|
18040
18462
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
18041
18463
|
try {
|
|
18042
|
-
|
|
18464
|
+
execSync17("npm install --no-audit --no-fund", {
|
|
18043
18465
|
cwd: voiceDir(),
|
|
18044
18466
|
stdio: "pipe",
|
|
18045
18467
|
timeout: 12e4
|
|
@@ -18060,7 +18482,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18060
18482
|
}
|
|
18061
18483
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
18062
18484
|
try {
|
|
18063
|
-
|
|
18485
|
+
execSync17("npm install --no-audit --no-fund", {
|
|
18064
18486
|
cwd: voiceDir(),
|
|
18065
18487
|
stdio: "pipe",
|
|
18066
18488
|
timeout: 12e4
|
|
@@ -18084,10 +18506,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18084
18506
|
const dir = modelDir(id);
|
|
18085
18507
|
const onnxPath = modelOnnxPath(id);
|
|
18086
18508
|
const configPath = modelConfigPath(id);
|
|
18087
|
-
if (
|
|
18509
|
+
if (existsSync20(onnxPath) && existsSync20(configPath))
|
|
18088
18510
|
return;
|
|
18089
18511
|
mkdirSync9(dir, { recursive: true });
|
|
18090
|
-
if (!
|
|
18512
|
+
if (!existsSync20(configPath)) {
|
|
18091
18513
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
18092
18514
|
const configResp = await fetch(model.configUrl);
|
|
18093
18515
|
if (!configResp.ok)
|
|
@@ -18095,7 +18517,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18095
18517
|
const configText = await configResp.text();
|
|
18096
18518
|
writeFileSync9(configPath, configText);
|
|
18097
18519
|
}
|
|
18098
|
-
if (!
|
|
18520
|
+
if (!existsSync20(onnxPath)) {
|
|
18099
18521
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
18100
18522
|
const onnxResp = await fetch(model.onnxUrl);
|
|
18101
18523
|
if (!onnxResp.ok)
|
|
@@ -18131,10 +18553,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
18131
18553
|
throw new Error("ONNX runtime not loaded");
|
|
18132
18554
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
18133
18555
|
const configPath = modelConfigPath(this.modelId);
|
|
18134
|
-
if (!
|
|
18556
|
+
if (!existsSync20(onnxPath) || !existsSync20(configPath)) {
|
|
18135
18557
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
18136
18558
|
}
|
|
18137
|
-
this.config = JSON.parse(
|
|
18559
|
+
this.config = JSON.parse(readFileSync16(configPath, "utf8"));
|
|
18138
18560
|
renderInfo("Loading voice model...");
|
|
18139
18561
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
18140
18562
|
executionProviders: ["cpu"],
|
|
@@ -18635,10 +19057,10 @@ var init_stream_renderer = __esm({
|
|
|
18635
19057
|
|
|
18636
19058
|
// packages/cli/dist/tui/edit-history.js
|
|
18637
19059
|
import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
|
|
18638
|
-
import { join as
|
|
19060
|
+
import { join as join27 } from "node:path";
|
|
18639
19061
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
18640
|
-
const historyDir =
|
|
18641
|
-
const logPath =
|
|
19062
|
+
const historyDir = join27(repoRoot, ".oa", "history");
|
|
19063
|
+
const logPath = join27(historyDir, "edits.jsonl");
|
|
18642
19064
|
try {
|
|
18643
19065
|
mkdirSync10(historyDir, { recursive: true });
|
|
18644
19066
|
} catch {
|
|
@@ -18749,9 +19171,9 @@ var init_edit_history = __esm({
|
|
|
18749
19171
|
});
|
|
18750
19172
|
|
|
18751
19173
|
// packages/cli/dist/tui/dream-engine.js
|
|
18752
|
-
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as
|
|
18753
|
-
import { join as
|
|
18754
|
-
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";
|
|
18755
19177
|
function adaptTool(tool) {
|
|
18756
19178
|
return {
|
|
18757
19179
|
name: tool.name,
|
|
@@ -18925,12 +19347,12 @@ var init_dream_engine = __esm({
|
|
|
18925
19347
|
const content = String(args["content"] ?? "");
|
|
18926
19348
|
if (!rawPath)
|
|
18927
19349
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
18928
|
-
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);
|
|
18929
19351
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
18930
19352
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
18931
19353
|
}
|
|
18932
19354
|
try {
|
|
18933
|
-
const dir =
|
|
19355
|
+
const dir = join28(targetPath, "..");
|
|
18934
19356
|
mkdirSync11(dir, { recursive: true });
|
|
18935
19357
|
writeFileSync10(targetPath, content, "utf-8");
|
|
18936
19358
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -18960,15 +19382,15 @@ var init_dream_engine = __esm({
|
|
|
18960
19382
|
const rawPath = String(args["path"] ?? "");
|
|
18961
19383
|
const oldStr = String(args["old_string"] ?? "");
|
|
18962
19384
|
const newStr = String(args["new_string"] ?? "");
|
|
18963
|
-
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);
|
|
18964
19386
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
18965
19387
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
18966
19388
|
}
|
|
18967
19389
|
try {
|
|
18968
|
-
if (!
|
|
19390
|
+
if (!existsSync21(targetPath)) {
|
|
18969
19391
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
18970
19392
|
}
|
|
18971
|
-
let content =
|
|
19393
|
+
let content = readFileSync17(targetPath, "utf-8");
|
|
18972
19394
|
if (!content.includes(oldStr)) {
|
|
18973
19395
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
18974
19396
|
}
|
|
@@ -19004,7 +19426,7 @@ var init_dream_engine = __esm({
|
|
|
19004
19426
|
}
|
|
19005
19427
|
}
|
|
19006
19428
|
try {
|
|
19007
|
-
const output =
|
|
19429
|
+
const output = execSync18(cmd, {
|
|
19008
19430
|
cwd: this.repoRoot,
|
|
19009
19431
|
timeout: 3e4,
|
|
19010
19432
|
encoding: "utf-8",
|
|
@@ -19027,7 +19449,7 @@ var init_dream_engine = __esm({
|
|
|
19027
19449
|
constructor(config, repoRoot) {
|
|
19028
19450
|
this.config = config;
|
|
19029
19451
|
this.repoRoot = repoRoot;
|
|
19030
|
-
this.dreamsDir =
|
|
19452
|
+
this.dreamsDir = join28(repoRoot, ".oa", "dreams");
|
|
19031
19453
|
this.state = {
|
|
19032
19454
|
mode: "default",
|
|
19033
19455
|
active: false,
|
|
@@ -19099,7 +19521,7 @@ ${result.summary}`;
|
|
|
19099
19521
|
if (mode !== "default" || cycle === totalCycles) {
|
|
19100
19522
|
renderDreamContraction(cycle);
|
|
19101
19523
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
19102
|
-
const summaryPath =
|
|
19524
|
+
const summaryPath = join28(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
19103
19525
|
writeFileSync10(summaryPath, cycleSummary, "utf-8");
|
|
19104
19526
|
}
|
|
19105
19527
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -19222,29 +19644,29 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
19222
19644
|
}
|
|
19223
19645
|
/** Save workspace backup for lucid mode */
|
|
19224
19646
|
saveVersionCheckpoint(cycle) {
|
|
19225
|
-
const checkpointDir =
|
|
19647
|
+
const checkpointDir = join28(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
19226
19648
|
try {
|
|
19227
19649
|
mkdirSync11(checkpointDir, { recursive: true });
|
|
19228
19650
|
try {
|
|
19229
|
-
const gitStatus =
|
|
19651
|
+
const gitStatus = execSync18("git status --porcelain", {
|
|
19230
19652
|
cwd: this.repoRoot,
|
|
19231
19653
|
encoding: "utf-8",
|
|
19232
19654
|
timeout: 1e4
|
|
19233
19655
|
});
|
|
19234
|
-
const gitDiff =
|
|
19656
|
+
const gitDiff = execSync18("git diff", {
|
|
19235
19657
|
cwd: this.repoRoot,
|
|
19236
19658
|
encoding: "utf-8",
|
|
19237
19659
|
timeout: 1e4
|
|
19238
19660
|
});
|
|
19239
|
-
const gitHash =
|
|
19661
|
+
const gitHash = execSync18("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
19240
19662
|
cwd: this.repoRoot,
|
|
19241
19663
|
encoding: "utf-8",
|
|
19242
19664
|
timeout: 5e3
|
|
19243
19665
|
}).trim();
|
|
19244
|
-
writeFileSync10(
|
|
19245
|
-
writeFileSync10(
|
|
19246
|
-
writeFileSync10(
|
|
19247
|
-
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({
|
|
19248
19670
|
cycle,
|
|
19249
19671
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19250
19672
|
gitHash,
|
|
@@ -19252,7 +19674,7 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
19252
19674
|
}, null, 2), "utf-8");
|
|
19253
19675
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
19254
19676
|
} catch {
|
|
19255
|
-
writeFileSync10(
|
|
19677
|
+
writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
19256
19678
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
19257
19679
|
}
|
|
19258
19680
|
} catch (err) {
|
|
@@ -19310,14 +19732,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
19310
19732
|
---
|
|
19311
19733
|
*Auto-generated by open-agents dream engine*
|
|
19312
19734
|
`;
|
|
19313
|
-
writeFileSync10(
|
|
19735
|
+
writeFileSync10(join28(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
19314
19736
|
} catch {
|
|
19315
19737
|
}
|
|
19316
19738
|
}
|
|
19317
19739
|
/** Save dream state for resume/inspection */
|
|
19318
19740
|
saveDreamState() {
|
|
19319
19741
|
try {
|
|
19320
|
-
writeFileSync10(
|
|
19742
|
+
writeFileSync10(join28(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
19321
19743
|
} catch {
|
|
19322
19744
|
}
|
|
19323
19745
|
}
|
|
@@ -20149,22 +20571,22 @@ var init_status_bar = __esm({
|
|
|
20149
20571
|
import * as readline2 from "node:readline";
|
|
20150
20572
|
import { Writable } from "node:stream";
|
|
20151
20573
|
import { cwd } from "node:process";
|
|
20152
|
-
import { resolve as
|
|
20574
|
+
import { resolve as resolve18, join as join29, dirname as dirname8, extname as extname9 } from "node:path";
|
|
20153
20575
|
import { createRequire as createRequire2 } from "node:module";
|
|
20154
20576
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
20155
|
-
import { readFileSync as
|
|
20156
|
-
import { existsSync as
|
|
20577
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
20578
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
20157
20579
|
function getVersion() {
|
|
20158
20580
|
try {
|
|
20159
20581
|
const require2 = createRequire2(import.meta.url);
|
|
20160
20582
|
const thisDir = dirname8(fileURLToPath5(import.meta.url));
|
|
20161
20583
|
const candidates = [
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20584
|
+
join29(thisDir, "..", "package.json"),
|
|
20585
|
+
join29(thisDir, "..", "..", "package.json"),
|
|
20586
|
+
join29(thisDir, "..", "..", "..", "package.json")
|
|
20165
20587
|
];
|
|
20166
20588
|
for (const pkgPath of candidates) {
|
|
20167
|
-
if (
|
|
20589
|
+
if (existsSync22(pkgPath)) {
|
|
20168
20590
|
const pkg = require2(pkgPath);
|
|
20169
20591
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
20170
20592
|
return pkg.version ?? "0.0.0";
|
|
@@ -20254,7 +20676,10 @@ function buildTools(repoRoot, config) {
|
|
|
20254
20676
|
// Vision tools (Moondream — desktop awareness + point-and-click)
|
|
20255
20677
|
new VisionTool(repoRoot),
|
|
20256
20678
|
new DesktopClickTool(repoRoot),
|
|
20257
|
-
new DesktopDescribeTool(repoRoot)
|
|
20679
|
+
new DesktopDescribeTool(repoRoot),
|
|
20680
|
+
// PDF tools (OCR + text extraction)
|
|
20681
|
+
new OcrPdfTool(repoRoot),
|
|
20682
|
+
new PdfToTextTool(repoRoot)
|
|
20258
20683
|
];
|
|
20259
20684
|
return [
|
|
20260
20685
|
...executionTools.map(adaptTool2),
|
|
@@ -20558,7 +20983,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
20558
20983
|
} };
|
|
20559
20984
|
}
|
|
20560
20985
|
async function startInteractive(config, repoPath) {
|
|
20561
|
-
const repoRoot =
|
|
20986
|
+
const repoRoot = resolve18(repoPath ?? cwd());
|
|
20562
20987
|
const resumeFlag = process.env.__OA_RESUMED ?? "";
|
|
20563
20988
|
const isResumed = resumeFlag !== "";
|
|
20564
20989
|
const hasTaskToResume = resumeFlag === "1";
|
|
@@ -20710,14 +21135,14 @@ async function startInteractive(config, repoPath) {
|
|
|
20710
21135
|
renderInfo(msg);
|
|
20711
21136
|
statusBar.endContentWrite();
|
|
20712
21137
|
}
|
|
20713
|
-
}, () => new Promise((
|
|
21138
|
+
}, () => new Promise((resolve21) => {
|
|
20714
21139
|
depSudoPromptPending = true;
|
|
20715
21140
|
depSudoResolver = (pw) => {
|
|
20716
21141
|
depSudoPromptPending = false;
|
|
20717
21142
|
depSudoResolver = null;
|
|
20718
21143
|
if (pw)
|
|
20719
21144
|
sessionSudoPassword = pw;
|
|
20720
|
-
|
|
21145
|
+
resolve21(pw);
|
|
20721
21146
|
};
|
|
20722
21147
|
if (statusBar?.isActive) {
|
|
20723
21148
|
statusBar.beginContentWrite();
|
|
@@ -21012,7 +21437,7 @@ async function startInteractive(config, repoPath) {
|
|
|
21012
21437
|
listenSetMode(mode) {
|
|
21013
21438
|
const engine = getListenEngine();
|
|
21014
21439
|
engine.setMode(mode);
|
|
21015
|
-
return mode === "auto" ? "Auto mode: transcriptions auto-submit after 3s silence" : "
|
|
21440
|
+
return mode === "auto" ? "Auto mode: transcriptions auto-submit after 3s silence" : "Manual mode: press Enter to submit transcriptions (auto-submit off)";
|
|
21016
21441
|
},
|
|
21017
21442
|
async listenStop() {
|
|
21018
21443
|
const engine = getListenEngine();
|
|
@@ -21229,13 +21654,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
21229
21654
|
}
|
|
21230
21655
|
}
|
|
21231
21656
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
21232
|
-
const isImage = isImagePath(cleanPath) &&
|
|
21233
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
21657
|
+
const isImage = isImagePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
|
|
21658
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
|
|
21234
21659
|
if (activeTask) {
|
|
21235
21660
|
if (isImage) {
|
|
21236
21661
|
try {
|
|
21237
|
-
const imgPath =
|
|
21238
|
-
const imgBuffer =
|
|
21662
|
+
const imgPath = resolve18(repoRoot, cleanPath);
|
|
21663
|
+
const imgBuffer = readFileSync18(imgPath);
|
|
21239
21664
|
const base64 = imgBuffer.toString("base64");
|
|
21240
21665
|
const ext = extname9(cleanPath).toLowerCase();
|
|
21241
21666
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -21248,7 +21673,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
21248
21673
|
} else if (isMedia) {
|
|
21249
21674
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
21250
21675
|
const engine = getListenEngine();
|
|
21251
|
-
const result = await engine.transcribeFile(
|
|
21676
|
+
const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
|
|
21252
21677
|
if (result) {
|
|
21253
21678
|
const transcript = `[Transcription of ${cleanPath}]
|
|
21254
21679
|
${result.text}`;
|
|
@@ -21281,7 +21706,7 @@ ${result.text}`;
|
|
|
21281
21706
|
if (isMedia && fullInput === input) {
|
|
21282
21707
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
21283
21708
|
const engine = getListenEngine();
|
|
21284
|
-
const result = await engine.transcribeFile(
|
|
21709
|
+
const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
|
|
21285
21710
|
if (result) {
|
|
21286
21711
|
fullInput = `The user has provided an audio/video file: ${cleanPath}.
|
|
21287
21712
|
|
|
@@ -21401,7 +21826,7 @@ ${c2.dim("(Use /quit to exit)")}
|
|
|
21401
21826
|
});
|
|
21402
21827
|
}
|
|
21403
21828
|
async function runWithTUI(task, config, repoPath) {
|
|
21404
|
-
const repoRoot =
|
|
21829
|
+
const repoRoot = resolve18(repoPath ?? cwd());
|
|
21405
21830
|
const needsSetup = isFirstRun() || !await isModelAvailable(config);
|
|
21406
21831
|
if (needsSetup && config.backendType === "ollama") {
|
|
21407
21832
|
const setupModel = await runSetupWizard(config);
|
|
@@ -21506,7 +21931,7 @@ import { glob } from "glob";
|
|
|
21506
21931
|
import ignore from "ignore";
|
|
21507
21932
|
import { readFile as readFile10, stat as stat4 } from "node:fs/promises";
|
|
21508
21933
|
import { createHash } from "node:crypto";
|
|
21509
|
-
import { join as
|
|
21934
|
+
import { join as join30, relative as relative3, extname as extname10, basename as basename11 } from "node:path";
|
|
21510
21935
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
21511
21936
|
var init_codebase_indexer = __esm({
|
|
21512
21937
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -21550,7 +21975,7 @@ var init_codebase_indexer = __esm({
|
|
|
21550
21975
|
const ig = ignore.default();
|
|
21551
21976
|
if (this.config.respectGitignore) {
|
|
21552
21977
|
try {
|
|
21553
|
-
const gitignoreContent = await readFile10(
|
|
21978
|
+
const gitignoreContent = await readFile10(join30(this.config.rootDir, ".gitignore"), "utf-8");
|
|
21554
21979
|
ig.add(gitignoreContent);
|
|
21555
21980
|
} catch {
|
|
21556
21981
|
}
|
|
@@ -21565,7 +21990,7 @@ var init_codebase_indexer = __esm({
|
|
|
21565
21990
|
for (const relativePath of files) {
|
|
21566
21991
|
if (ig.ignores(relativePath))
|
|
21567
21992
|
continue;
|
|
21568
|
-
const fullPath =
|
|
21993
|
+
const fullPath = join30(this.config.rootDir, relativePath);
|
|
21569
21994
|
try {
|
|
21570
21995
|
const fileStat = await stat4(fullPath);
|
|
21571
21996
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -21588,7 +22013,7 @@ var init_codebase_indexer = __esm({
|
|
|
21588
22013
|
}
|
|
21589
22014
|
buildTree(files) {
|
|
21590
22015
|
const root = {
|
|
21591
|
-
name:
|
|
22016
|
+
name: basename11(this.config.rootDir),
|
|
21592
22017
|
path: this.config.rootDir,
|
|
21593
22018
|
type: "directory",
|
|
21594
22019
|
children: []
|
|
@@ -21611,7 +22036,7 @@ var init_codebase_indexer = __esm({
|
|
|
21611
22036
|
if (!child) {
|
|
21612
22037
|
child = {
|
|
21613
22038
|
name: part,
|
|
21614
|
-
path:
|
|
22039
|
+
path: join30(current.path, part),
|
|
21615
22040
|
type: "directory",
|
|
21616
22041
|
children: []
|
|
21617
22042
|
};
|
|
@@ -21685,18 +22110,18 @@ var index_repo_exports = {};
|
|
|
21685
22110
|
__export(index_repo_exports, {
|
|
21686
22111
|
indexRepoCommand: () => indexRepoCommand
|
|
21687
22112
|
});
|
|
21688
|
-
import { resolve as
|
|
21689
|
-
import { existsSync as
|
|
22113
|
+
import { resolve as resolve19 } from "node:path";
|
|
22114
|
+
import { existsSync as existsSync23, statSync as statSync9 } from "node:fs";
|
|
21690
22115
|
import { cwd as cwd2 } from "node:process";
|
|
21691
22116
|
async function indexRepoCommand(opts, _config) {
|
|
21692
|
-
const repoRoot =
|
|
22117
|
+
const repoRoot = resolve19(opts.repoPath ?? cwd2());
|
|
21693
22118
|
printHeader("Index Repository");
|
|
21694
22119
|
printInfo(`Indexing: ${repoRoot}`);
|
|
21695
|
-
if (!
|
|
22120
|
+
if (!existsSync23(repoRoot)) {
|
|
21696
22121
|
printError(`Path does not exist: ${repoRoot}`);
|
|
21697
22122
|
process.exit(1);
|
|
21698
22123
|
}
|
|
21699
|
-
const stat5 =
|
|
22124
|
+
const stat5 = statSync9(repoRoot);
|
|
21700
22125
|
if (!stat5.isDirectory()) {
|
|
21701
22126
|
printError(`Path is not a directory: ${repoRoot}`);
|
|
21702
22127
|
process.exit(1);
|
|
@@ -21938,7 +22363,7 @@ var config_exports = {};
|
|
|
21938
22363
|
__export(config_exports, {
|
|
21939
22364
|
configCommand: () => configCommand
|
|
21940
22365
|
});
|
|
21941
|
-
import { join as
|
|
22366
|
+
import { join as join31, resolve as resolve20 } from "node:path";
|
|
21942
22367
|
import { homedir as homedir11 } from "node:os";
|
|
21943
22368
|
import { cwd as cwd3 } from "node:process";
|
|
21944
22369
|
function coerceForSettings(key, value) {
|
|
@@ -21959,7 +22384,7 @@ async function configCommand(opts, config) {
|
|
|
21959
22384
|
return handleShow(opts, config);
|
|
21960
22385
|
}
|
|
21961
22386
|
function handleShow(opts, config) {
|
|
21962
|
-
const repoRoot =
|
|
22387
|
+
const repoRoot = resolve20(opts.repoPath ?? cwd3());
|
|
21963
22388
|
printHeader("Configuration");
|
|
21964
22389
|
printSection("Active Settings (merged)");
|
|
21965
22390
|
printKeyValue("backendUrl", config.backendUrl, 2);
|
|
@@ -21991,7 +22416,7 @@ function handleShow(opts, config) {
|
|
|
21991
22416
|
}
|
|
21992
22417
|
}
|
|
21993
22418
|
printSection("Config File");
|
|
21994
|
-
printInfo(`~/.open-agents/config.json (${
|
|
22419
|
+
printInfo(`~/.open-agents/config.json (${join31(homedir11(), ".open-agents", "config.json")})`);
|
|
21995
22420
|
printSection("Priority Chain");
|
|
21996
22421
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
21997
22422
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -22024,13 +22449,13 @@ function handleSet(opts, _config) {
|
|
|
22024
22449
|
process.exit(1);
|
|
22025
22450
|
}
|
|
22026
22451
|
if (opts.local) {
|
|
22027
|
-
const repoRoot =
|
|
22452
|
+
const repoRoot = resolve20(opts.repoPath ?? cwd3());
|
|
22028
22453
|
try {
|
|
22029
22454
|
initOaDirectory(repoRoot);
|
|
22030
22455
|
const coerced = coerceForSettings(key, value);
|
|
22031
22456
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
22032
22457
|
printSuccess(`Project override set: ${key} = ${value}`);
|
|
22033
|
-
printInfo(`Saved to ${
|
|
22458
|
+
printInfo(`Saved to ${join31(repoRoot, ".oa", "settings.json")}`);
|
|
22034
22459
|
printInfo("This override applies only when running in this workspace.");
|
|
22035
22460
|
} catch (err) {
|
|
22036
22461
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -22182,7 +22607,7 @@ async function serveVllm(opts, config) {
|
|
|
22182
22607
|
await runVllmServer(args, opts.verbose ?? false);
|
|
22183
22608
|
}
|
|
22184
22609
|
async function runVllmServer(args, verbose) {
|
|
22185
|
-
return new Promise((
|
|
22610
|
+
return new Promise((resolve21, reject) => {
|
|
22186
22611
|
const child = spawn9("python", args, {
|
|
22187
22612
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
22188
22613
|
env: { ...process.env }
|
|
@@ -22217,10 +22642,10 @@ async function runVllmServer(args, verbose) {
|
|
|
22217
22642
|
child.once("exit", (code, signal) => {
|
|
22218
22643
|
if (signal) {
|
|
22219
22644
|
printInfo(`vLLM server stopped by signal ${signal}`);
|
|
22220
|
-
|
|
22645
|
+
resolve21();
|
|
22221
22646
|
} else if (code === 0) {
|
|
22222
22647
|
printSuccess("vLLM server exited cleanly");
|
|
22223
|
-
|
|
22648
|
+
resolve21();
|
|
22224
22649
|
} else {
|
|
22225
22650
|
printError(`vLLM server exited with code ${code}`);
|
|
22226
22651
|
reject(new Error(`vLLM exited with code ${code}`));
|
|
@@ -22247,9 +22672,9 @@ var eval_exports = {};
|
|
|
22247
22672
|
__export(eval_exports, {
|
|
22248
22673
|
evalCommand: () => evalCommand
|
|
22249
22674
|
});
|
|
22250
|
-
import { tmpdir as
|
|
22675
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
22251
22676
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
22252
|
-
import { join as
|
|
22677
|
+
import { join as join32 } from "node:path";
|
|
22253
22678
|
async function evalCommand(opts, config) {
|
|
22254
22679
|
const suiteName = opts.suite ?? "basic";
|
|
22255
22680
|
const suite = SUITES[suiteName];
|
|
@@ -22370,9 +22795,9 @@ async function evalCommand(opts, config) {
|
|
|
22370
22795
|
process.exit(failed > 0 ? 1 : 0);
|
|
22371
22796
|
}
|
|
22372
22797
|
function createTempEvalRepo() {
|
|
22373
|
-
const dir =
|
|
22798
|
+
const dir = join32(tmpdir6(), `open-agents-eval-${Date.now()}`);
|
|
22374
22799
|
mkdirSync12(dir, { recursive: true });
|
|
22375
|
-
writeFileSync11(
|
|
22800
|
+
writeFileSync11(join32(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
22376
22801
|
return dir;
|
|
22377
22802
|
}
|
|
22378
22803
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -22432,7 +22857,7 @@ init_updater();
|
|
|
22432
22857
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
22433
22858
|
import { createRequire as createRequire3 } from "node:module";
|
|
22434
22859
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
22435
|
-
import { dirname as dirname9, join as
|
|
22860
|
+
import { dirname as dirname9, join as join33 } from "node:path";
|
|
22436
22861
|
|
|
22437
22862
|
// packages/cli/dist/cli.js
|
|
22438
22863
|
import { createInterface } from "node:readline";
|
|
@@ -22539,7 +22964,7 @@ init_output();
|
|
|
22539
22964
|
function getVersion2() {
|
|
22540
22965
|
try {
|
|
22541
22966
|
const require2 = createRequire3(import.meta.url);
|
|
22542
|
-
const pkgPath =
|
|
22967
|
+
const pkgPath = join33(dirname9(fileURLToPath6(import.meta.url)), "..", "package.json");
|
|
22543
22968
|
const pkg = require2(pkgPath);
|
|
22544
22969
|
return pkg.version;
|
|
22545
22970
|
} catch {
|