open-agents-ai 0.142.2 → 0.144.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -1370,7 +1370,7 @@ ${stdinInput ?? ""}`);
|
|
|
1370
1370
|
}
|
|
1371
1371
|
runCommand(command, timeout, stdinInput) {
|
|
1372
1372
|
const start = performance.now();
|
|
1373
|
-
return new Promise((
|
|
1373
|
+
return new Promise((resolve33) => {
|
|
1374
1374
|
const child = spawn("bash", ["-c", command], {
|
|
1375
1375
|
cwd: this.workingDir,
|
|
1376
1376
|
env: {
|
|
@@ -1395,7 +1395,7 @@ ${stdinInput ?? ""}`);
|
|
|
1395
1395
|
clearTimeout(timer);
|
|
1396
1396
|
if (exitFlushTimer)
|
|
1397
1397
|
clearTimeout(exitFlushTimer);
|
|
1398
|
-
|
|
1398
|
+
resolve33(result);
|
|
1399
1399
|
};
|
|
1400
1400
|
const timer = setTimeout(() => {
|
|
1401
1401
|
killed = true;
|
|
@@ -1492,6 +1492,61 @@ ${stderr}` : ""),
|
|
|
1492
1492
|
// packages/execution/dist/tools/file-read.js
|
|
1493
1493
|
import { readFile } from "node:fs/promises";
|
|
1494
1494
|
import { resolve } from "node:path";
|
|
1495
|
+
function computeMaxUngatedLines(contextWindow) {
|
|
1496
|
+
if (contextWindow <= 0)
|
|
1497
|
+
return 200;
|
|
1498
|
+
const budget = Math.floor(contextWindow * 0.15);
|
|
1499
|
+
const maxLines = Math.floor(budget / 10);
|
|
1500
|
+
return Math.max(80, Math.min(500, maxLines));
|
|
1501
|
+
}
|
|
1502
|
+
function buildStructuralPreview(lines, filePath, maxLines) {
|
|
1503
|
+
const total = lines.length;
|
|
1504
|
+
const HEAD = Math.min(30, Math.floor(maxLines * 0.35));
|
|
1505
|
+
const TAIL = Math.min(15, Math.floor(maxLines * 0.15));
|
|
1506
|
+
const parts = [];
|
|
1507
|
+
parts.push(`# ${filePath} \u2014 ${total} lines (showing structural preview)
|
|
1508
|
+
`);
|
|
1509
|
+
parts.push(`## Lines 1-${HEAD}:`);
|
|
1510
|
+
for (let i = 0; i < HEAD; i++) {
|
|
1511
|
+
parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
|
|
1512
|
+
}
|
|
1513
|
+
const sigs = [];
|
|
1514
|
+
for (let i = HEAD; i < total - TAIL; i++) {
|
|
1515
|
+
const line = lines[i];
|
|
1516
|
+
if (SIG_PATTERNS.some((p) => p.test(line))) {
|
|
1517
|
+
sigs.push(`${String(i + 1).padStart(6)} | ${line}`);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (sigs.length > 0) {
|
|
1521
|
+
parts.push(`
|
|
1522
|
+
## Signatures (lines ${HEAD + 1}-${total - TAIL}) \u2014 ${sigs.length} found:`);
|
|
1523
|
+
const maxSigs = Math.floor(maxLines * 0.4);
|
|
1524
|
+
if (sigs.length > maxSigs) {
|
|
1525
|
+
parts.push(...sigs.slice(0, maxSigs));
|
|
1526
|
+
parts.push(` ... ${sigs.length - maxSigs} more signatures`);
|
|
1527
|
+
} else {
|
|
1528
|
+
parts.push(...sigs);
|
|
1529
|
+
}
|
|
1530
|
+
} else {
|
|
1531
|
+
parts.push(`
|
|
1532
|
+
## Lines ${HEAD + 1}-${total - TAIL}: ${total - HEAD - TAIL} lines (no signatures detected)`);
|
|
1533
|
+
}
|
|
1534
|
+
if (TAIL > 0) {
|
|
1535
|
+
const tailStart = total - TAIL;
|
|
1536
|
+
parts.push(`
|
|
1537
|
+
## Lines ${tailStart + 1}-${total}:`);
|
|
1538
|
+
for (let i = tailStart; i < total; i++) {
|
|
1539
|
+
parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
parts.push(``);
|
|
1543
|
+
parts.push(`To read a specific section: file_read(path="${filePath}", offset=LINE, limit=50)`);
|
|
1544
|
+
parts.push(`To search for a pattern: grep_search(pattern="...", path="${filePath}")`);
|
|
1545
|
+
if (sigs.length > 0) {
|
|
1546
|
+
parts.push(`To explore interactively: file_explore(strategy="search", path="${filePath}", query="...")`);
|
|
1547
|
+
}
|
|
1548
|
+
return parts.join("\n");
|
|
1549
|
+
}
|
|
1495
1550
|
function extractPath(args) {
|
|
1496
1551
|
if (typeof args["path"] === "string" && args["path"].trim()) {
|
|
1497
1552
|
return args["path"].trim();
|
|
@@ -1516,13 +1571,25 @@ function extractPath(args) {
|
|
|
1516
1571
|
}
|
|
1517
1572
|
return null;
|
|
1518
1573
|
}
|
|
1519
|
-
var FileReadTool;
|
|
1574
|
+
var SIG_PATTERNS, FileReadTool;
|
|
1520
1575
|
var init_file_read = __esm({
|
|
1521
1576
|
"packages/execution/dist/tools/file-read.js"() {
|
|
1522
1577
|
"use strict";
|
|
1578
|
+
SIG_PATTERNS = [
|
|
1579
|
+
/^\s*(export\s+)?(async\s+)?function\s+\w+/,
|
|
1580
|
+
/^\s*(export\s+)?(abstract\s+)?class\s+\w+/,
|
|
1581
|
+
/^\s*(export\s+)?interface\s+\w+/,
|
|
1582
|
+
/^\s*(export\s+)?type\s+\w+\s*=/,
|
|
1583
|
+
/^\s*(export\s+)?enum\s+\w+/,
|
|
1584
|
+
/^\s*(?:public|private|protected|static|async|get|set)\s+\w+\s*[(<]/,
|
|
1585
|
+
/^\s*(pub\s+)?(async\s+)?fn\s+\w+/,
|
|
1586
|
+
/^\s*(pub\s+)?struct\s+\w+/,
|
|
1587
|
+
/^\s*def\s+\w+/,
|
|
1588
|
+
/^\s*class\s+\w+/
|
|
1589
|
+
];
|
|
1523
1590
|
FileReadTool = class {
|
|
1524
1591
|
name = "file_read";
|
|
1525
|
-
description = "Read the contents of a file";
|
|
1592
|
+
description = "Read the contents of a file. For large files (200+ lines), returns a structural preview with signatures \u2014 use offset/limit to read specific sections.";
|
|
1526
1593
|
parameters = {
|
|
1527
1594
|
type: "object",
|
|
1528
1595
|
properties: {
|
|
@@ -1537,7 +1604,7 @@ var init_file_read = __esm({
|
|
|
1537
1604
|
constructor(workingDir) {
|
|
1538
1605
|
this.workingDir = workingDir;
|
|
1539
1606
|
}
|
|
1540
|
-
/** Set actual context window size
|
|
1607
|
+
/** Set actual context window size for proportional auto-windowing */
|
|
1541
1608
|
setContextWindowSize(size) {
|
|
1542
1609
|
this._contextWindowSize = size;
|
|
1543
1610
|
}
|
|
@@ -1559,24 +1626,25 @@ var init_file_read = __esm({
|
|
|
1559
1626
|
const content = await readFile(fullPath, "utf-8");
|
|
1560
1627
|
let lines = content.split("\n");
|
|
1561
1628
|
const totalLines = lines.length;
|
|
1562
|
-
if (offset !== void 0) {
|
|
1563
|
-
const startIdx = Math.max(0, offset - 1);
|
|
1629
|
+
if (offset !== void 0 || limit !== void 0) {
|
|
1630
|
+
const startIdx = Math.max(0, (offset ?? 1) - 1);
|
|
1564
1631
|
lines = lines.slice(startIdx, limit ? startIdx + limit : void 0);
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1632
|
+
const numbered2 = lines.map((line, i) => `${String(startIdx + i + 1).padStart(6)} | ${line}`).join("\n");
|
|
1633
|
+
return {
|
|
1634
|
+
success: true,
|
|
1635
|
+
output: numbered2,
|
|
1636
|
+
durationMs: performance.now() - start
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
const maxLines = computeMaxUngatedLines(this._contextWindowSize);
|
|
1640
|
+
if (totalLines > maxLines) {
|
|
1641
|
+
return {
|
|
1642
|
+
success: true,
|
|
1643
|
+
output: buildStructuralPreview(lines, filePath, maxLines),
|
|
1644
|
+
durationMs: performance.now() - start
|
|
1645
|
+
};
|
|
1578
1646
|
}
|
|
1579
|
-
const numbered = lines.map((line, i) => `${String(i +
|
|
1647
|
+
const numbered = lines.map((line, i) => `${String(i + 1).padStart(6)} | ${line}`).join("\n");
|
|
1580
1648
|
return {
|
|
1581
1649
|
success: true,
|
|
1582
1650
|
output: numbered,
|
|
@@ -2556,7 +2624,7 @@ ${JSON.stringify(extracted, null, 2)}`);
|
|
|
2556
2624
|
return null;
|
|
2557
2625
|
}
|
|
2558
2626
|
runProcess(cmd, args, timeoutMs) {
|
|
2559
|
-
return new Promise((
|
|
2627
|
+
return new Promise((resolve33, reject) => {
|
|
2560
2628
|
const proc = execFile3(cmd, args, {
|
|
2561
2629
|
timeout: timeoutMs,
|
|
2562
2630
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -2566,7 +2634,7 @@ ${JSON.stringify(extracted, null, 2)}`);
|
|
|
2566
2634
|
reject(new Error(`Process timeout after ${timeoutMs}ms`));
|
|
2567
2635
|
return;
|
|
2568
2636
|
}
|
|
2569
|
-
|
|
2637
|
+
resolve33({
|
|
2570
2638
|
stdout: String(stdout),
|
|
2571
2639
|
stderr: String(stderr),
|
|
2572
2640
|
exitCode: error ? error.code ?? 1 : 0
|
|
@@ -9975,7 +10043,7 @@ var init_custom_tool = __esm({
|
|
|
9975
10043
|
}
|
|
9976
10044
|
/** Execute a single shell command and return output */
|
|
9977
10045
|
runCommand(command) {
|
|
9978
|
-
return new Promise((
|
|
10046
|
+
return new Promise((resolve33) => {
|
|
9979
10047
|
const child = spawn4("bash", ["-c", command], {
|
|
9980
10048
|
cwd: this.workingDir,
|
|
9981
10049
|
env: { ...process.env, CI: "true", NO_COLOR: "1" },
|
|
@@ -10000,11 +10068,11 @@ var init_custom_tool = __esm({
|
|
|
10000
10068
|
child.kill("SIGTERM");
|
|
10001
10069
|
} catch {
|
|
10002
10070
|
}
|
|
10003
|
-
|
|
10071
|
+
resolve33({ success: false, output: stdout, error: "Command timed out after 60s" });
|
|
10004
10072
|
}, 6e4);
|
|
10005
10073
|
child.on("close", (code) => {
|
|
10006
10074
|
clearTimeout(timer);
|
|
10007
|
-
|
|
10075
|
+
resolve33({
|
|
10008
10076
|
success: code === 0,
|
|
10009
10077
|
output: stdout + (stderr && code === 0 ? `
|
|
10010
10078
|
STDERR:
|
|
@@ -10014,7 +10082,7 @@ ${stderr}` : ""),
|
|
|
10014
10082
|
});
|
|
10015
10083
|
child.on("error", (err) => {
|
|
10016
10084
|
clearTimeout(timer);
|
|
10017
|
-
|
|
10085
|
+
resolve33({ success: false, output: stdout, error: err.message });
|
|
10018
10086
|
});
|
|
10019
10087
|
});
|
|
10020
10088
|
}
|
|
@@ -11481,7 +11549,7 @@ import { writeFile as writeFile8, mkdtemp, rm, readdir as readdir3, stat } from
|
|
|
11481
11549
|
import { join as join18 } from "node:path";
|
|
11482
11550
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11483
11551
|
function runProcess(cmd, args, options) {
|
|
11484
|
-
return new Promise((
|
|
11552
|
+
return new Promise((resolve33) => {
|
|
11485
11553
|
const proc = spawn6(cmd, args, {
|
|
11486
11554
|
cwd: options.cwd,
|
|
11487
11555
|
timeout: options.timeout,
|
|
@@ -11511,7 +11579,7 @@ function runProcess(cmd, args, options) {
|
|
|
11511
11579
|
}
|
|
11512
11580
|
});
|
|
11513
11581
|
proc.on("error", (err) => {
|
|
11514
|
-
|
|
11582
|
+
resolve33({
|
|
11515
11583
|
stdout,
|
|
11516
11584
|
stderr: stderr || err.message,
|
|
11517
11585
|
exitCode: 1,
|
|
@@ -11523,7 +11591,7 @@ function runProcess(cmd, args, options) {
|
|
|
11523
11591
|
if (signal === "SIGTERM" || signal === "SIGKILL") {
|
|
11524
11592
|
timedOut = true;
|
|
11525
11593
|
}
|
|
11526
|
-
|
|
11594
|
+
resolve33({
|
|
11527
11595
|
stdout,
|
|
11528
11596
|
stderr,
|
|
11529
11597
|
exitCode: code ?? (timedOut ? 124 : 1),
|
|
@@ -12006,7 +12074,7 @@ Justification: ${justification || "(none provided)"}`,
|
|
|
12006
12074
|
})();
|
|
12007
12075
|
const ipfsResult = await Promise.race([
|
|
12008
12076
|
ipfsPromise,
|
|
12009
|
-
new Promise((
|
|
12077
|
+
new Promise((resolve33) => setTimeout(() => resolve33(null), 2e3))
|
|
12010
12078
|
]);
|
|
12011
12079
|
if (ipfsResult && ipfsResult.success) {
|
|
12012
12080
|
const cidData = JSON.parse(ipfsResult.output);
|
|
@@ -12450,7 +12518,7 @@ print("__OA_REPL_READY__")
|
|
|
12450
12518
|
return;
|
|
12451
12519
|
const sockId = randomBytes3(8).toString("hex");
|
|
12452
12520
|
this.ipcPath = join20(tmpdir3(), `oa-repl-ipc-${sockId}.sock`);
|
|
12453
|
-
return new Promise((
|
|
12521
|
+
return new Promise((resolve33, reject) => {
|
|
12454
12522
|
this.ipcServer = createServer((conn) => {
|
|
12455
12523
|
let buffer = new Uint8Array(0);
|
|
12456
12524
|
conn.on("data", (chunk) => {
|
|
@@ -12466,7 +12534,7 @@ print("__OA_REPL_READY__")
|
|
|
12466
12534
|
});
|
|
12467
12535
|
});
|
|
12468
12536
|
this.ipcServer.on("error", reject);
|
|
12469
|
-
this.ipcServer.listen(this.ipcPath, () =>
|
|
12537
|
+
this.ipcServer.listen(this.ipcPath, () => resolve33());
|
|
12470
12538
|
});
|
|
12471
12539
|
}
|
|
12472
12540
|
async processIpcBuffer(conn, input) {
|
|
@@ -12529,9 +12597,9 @@ print("__OA_REPL_READY__")
|
|
|
12529
12597
|
}
|
|
12530
12598
|
// ── Code execution ─────────────────────────────────────────────────────
|
|
12531
12599
|
executeCode(code, isInit = false) {
|
|
12532
|
-
return new Promise((
|
|
12600
|
+
return new Promise((resolve33) => {
|
|
12533
12601
|
if (!this.proc?.stdin || !this.proc?.stdout || !this.proc?.stderr) {
|
|
12534
|
-
|
|
12602
|
+
resolve33({ success: false, output: "REPL process not available", error: "No process", durationMs: 0 });
|
|
12535
12603
|
return;
|
|
12536
12604
|
}
|
|
12537
12605
|
const sentinel = `__OA_SENTINEL_${randomBytes3(6).toString("hex")}__`;
|
|
@@ -12541,7 +12609,7 @@ print("__OA_REPL_READY__")
|
|
|
12541
12609
|
const timeout = setTimeout(() => {
|
|
12542
12610
|
if (!resolved) {
|
|
12543
12611
|
resolved = true;
|
|
12544
|
-
|
|
12612
|
+
resolve33({
|
|
12545
12613
|
success: false,
|
|
12546
12614
|
output: stdout || "Execution timed out",
|
|
12547
12615
|
error: `Timeout after ${this.execTimeout / 1e3}s`,
|
|
@@ -12558,13 +12626,13 @@ print("__OA_REPL_READY__")
|
|
|
12558
12626
|
if (isInit) {
|
|
12559
12627
|
const ready = cleanOutput.includes("__OA_REPL_READY__");
|
|
12560
12628
|
const displayOutput = cleanOutput.replace("__OA_REPL_READY__", "").trim();
|
|
12561
|
-
|
|
12629
|
+
resolve33({
|
|
12562
12630
|
success: ready,
|
|
12563
12631
|
output: displayOutput || "REPL initialized",
|
|
12564
12632
|
durationMs: 0
|
|
12565
12633
|
});
|
|
12566
12634
|
} else {
|
|
12567
|
-
|
|
12635
|
+
resolve33({
|
|
12568
12636
|
success: true,
|
|
12569
12637
|
output: cleanOutput || "(no output)",
|
|
12570
12638
|
durationMs: 0
|
|
@@ -12573,7 +12641,7 @@ print("__OA_REPL_READY__")
|
|
|
12573
12641
|
}
|
|
12574
12642
|
if (stdout.length > 2e5) {
|
|
12575
12643
|
cleanup();
|
|
12576
|
-
|
|
12644
|
+
resolve33({
|
|
12577
12645
|
success: true,
|
|
12578
12646
|
output: stdout.slice(0, 2e5) + "\n[output truncated at 200KB]",
|
|
12579
12647
|
durationMs: 0
|
|
@@ -16812,6 +16880,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
|
|
|
16812
16880
|
import { execSync as execSync18, exec as execCb } from "node:child_process";
|
|
16813
16881
|
import { readFile as readFile15, writeFile as writeFile15, mkdir as mkdir11 } from "node:fs/promises";
|
|
16814
16882
|
import { resolve as resolve22, join as join32 } from "node:path";
|
|
16883
|
+
import { homedir as homedir8 } from "node:os";
|
|
16815
16884
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
16816
16885
|
function isValidCron(expr) {
|
|
16817
16886
|
const parts = expr.trim().split(/\s+/);
|
|
@@ -16941,6 +17010,31 @@ async function saveStore(workingDir, store) {
|
|
|
16941
17010
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
16942
17011
|
await writeFile15(join32(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
16943
17012
|
}
|
|
17013
|
+
function globalStoreDir() {
|
|
17014
|
+
return join32(homedir8(), ".open-agents", "scheduled");
|
|
17015
|
+
}
|
|
17016
|
+
async function loadGlobalStore() {
|
|
17017
|
+
try {
|
|
17018
|
+
const raw = await readFile15(join32(globalStoreDir(), "tasks.json"), "utf-8");
|
|
17019
|
+
return JSON.parse(raw);
|
|
17020
|
+
} catch {
|
|
17021
|
+
return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
17022
|
+
}
|
|
17023
|
+
}
|
|
17024
|
+
async function saveGlobalStore(store) {
|
|
17025
|
+
const dir = globalStoreDir();
|
|
17026
|
+
await mkdir11(dir, { recursive: true });
|
|
17027
|
+
await mkdir11(join32(dir, "logs"), { recursive: true });
|
|
17028
|
+
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17029
|
+
await writeFile15(join32(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
17030
|
+
}
|
|
17031
|
+
async function loadAllStores(workingDir) {
|
|
17032
|
+
const [local, global] = await Promise.all([
|
|
17033
|
+
loadStore(workingDir),
|
|
17034
|
+
loadGlobalStore()
|
|
17035
|
+
]);
|
|
17036
|
+
return { local, global };
|
|
17037
|
+
}
|
|
16944
17038
|
var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
|
|
16945
17039
|
var init_scheduler = __esm({
|
|
16946
17040
|
"packages/execution/dist/tools/scheduler.js"() {
|
|
@@ -16964,7 +17058,7 @@ var init_scheduler = __esm({
|
|
|
16964
17058
|
CRON_MARKER = "# OPEN-AGENTS-SCHEDULED:";
|
|
16965
17059
|
SchedulerTool = class {
|
|
16966
17060
|
name = "scheduler";
|
|
16967
|
-
description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', 'every 5 minutes', 'hourly', 'weekly'), natural language ('in 30m', 'at 14:30'), or raw cron expressions ('0 */2 * * *'). Tasks launch the agent automatically at the scheduled time.";
|
|
17061
|
+
description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', 'every 5 minutes', 'hourly', 'weekly'), natural language ('in 30m', 'at 14:30'), or raw cron expressions ('0 */2 * * *'). Scope: 'local' (default, stored in .oa/) or 'global' (stored in ~/.open-agents/, visible from all projects). Tasks launch the agent automatically at the scheduled time.";
|
|
16968
17062
|
parameters = {
|
|
16969
17063
|
type: "object",
|
|
16970
17064
|
properties: {
|
|
@@ -16992,6 +17086,11 @@ var init_scheduler = __esm({
|
|
|
16992
17086
|
one_shot: {
|
|
16993
17087
|
type: "boolean",
|
|
16994
17088
|
description: "If true, task auto-removes after first execution"
|
|
17089
|
+
},
|
|
17090
|
+
scope: {
|
|
17091
|
+
type: "string",
|
|
17092
|
+
enum: ["local", "global"],
|
|
17093
|
+
description: "Scope: 'local' (project .oa/, default) or 'global' (~/.open-agents/, visible from all projects)"
|
|
16995
17094
|
}
|
|
16996
17095
|
},
|
|
16997
17096
|
required: ["action"]
|
|
@@ -17053,6 +17152,7 @@ var init_scheduler = __esm({
|
|
|
17053
17152
|
const id = `sched-${randomBytes4(4).toString("hex")}`;
|
|
17054
17153
|
const oneShot = Boolean(args["one_shot"]);
|
|
17055
17154
|
const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : void 0;
|
|
17155
|
+
const scope = String(args["scope"] ?? "local");
|
|
17056
17156
|
const newTask = {
|
|
17057
17157
|
id,
|
|
17058
17158
|
task,
|
|
@@ -17062,11 +17162,19 @@ var init_scheduler = __esm({
|
|
|
17062
17162
|
enabled: true,
|
|
17063
17163
|
runCount: 0,
|
|
17064
17164
|
maxRuns,
|
|
17065
|
-
oneShot: oneShot || void 0
|
|
17165
|
+
oneShot: oneShot || void 0,
|
|
17166
|
+
scope,
|
|
17167
|
+
projectDir: resolve22(this.workingDir)
|
|
17066
17168
|
};
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17169
|
+
if (scope === "global") {
|
|
17170
|
+
const store = await loadGlobalStore();
|
|
17171
|
+
store.tasks.push(newTask);
|
|
17172
|
+
await saveGlobalStore(store);
|
|
17173
|
+
} else {
|
|
17174
|
+
const store = await loadStore(this.workingDir);
|
|
17175
|
+
store.tasks.push(newTask);
|
|
17176
|
+
await saveStore(this.workingDir, store);
|
|
17177
|
+
}
|
|
17070
17178
|
installCronJob(newTask, this.workingDir);
|
|
17071
17179
|
return {
|
|
17072
17180
|
success: true,
|
|
@@ -17075,6 +17183,7 @@ var init_scheduler = __esm({
|
|
|
17075
17183
|
` ID: ${id}`,
|
|
17076
17184
|
` Task: ${task}`,
|
|
17077
17185
|
` Schedule: ${describeCron(cronExpr)} (${cronExpr})`,
|
|
17186
|
+
` Scope: ${scope}${scope === "global" ? " (visible from all projects)" : " (this project only)"}`,
|
|
17078
17187
|
oneShot ? ` Mode: one-shot (auto-removes after first run)` : "",
|
|
17079
17188
|
maxRuns ? ` Max runs: ${maxRuns}` : "",
|
|
17080
17189
|
` Status: enabled`,
|
|
@@ -17086,28 +17195,53 @@ var init_scheduler = __esm({
|
|
|
17086
17195
|
};
|
|
17087
17196
|
}
|
|
17088
17197
|
async listTasks(start) {
|
|
17089
|
-
const
|
|
17198
|
+
const { local, global } = await loadAllStores(this.workingDir);
|
|
17090
17199
|
const cronJobs = listCronJobs();
|
|
17091
|
-
|
|
17200
|
+
const totalCount = local.tasks.length + global.tasks.length;
|
|
17201
|
+
if (totalCount === 0) {
|
|
17092
17202
|
return {
|
|
17093
17203
|
success: true,
|
|
17094
17204
|
output: "No scheduled tasks. Use scheduler(action='create', task='...', schedule='daily') to create one.",
|
|
17095
17205
|
durationMs: performance.now() - start
|
|
17096
17206
|
};
|
|
17097
17207
|
}
|
|
17098
|
-
const lines = [
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
17102
|
-
const
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
lines.push(`
|
|
17110
|
-
|
|
17208
|
+
const lines = [];
|
|
17209
|
+
if (local.tasks.length > 0) {
|
|
17210
|
+
lines.push(`Local Tasks \u2014 this project (${local.tasks.length}):
|
|
17211
|
+
`);
|
|
17212
|
+
for (const t of local.tasks) {
|
|
17213
|
+
const status = t.enabled ? "enabled" : "PAUSED";
|
|
17214
|
+
const cronInstalled = cronJobs.some((j) => j.id === t.id);
|
|
17215
|
+
const cronStatus = cronInstalled ? "" : " [cron not installed]";
|
|
17216
|
+
lines.push(` [${t.id}] ${status}${cronStatus} [local]`);
|
|
17217
|
+
lines.push(` Task: ${t.task.slice(0, 100)}${t.task.length > 100 ? "..." : ""}`);
|
|
17218
|
+
lines.push(` Schedule: ${t.nextRunDescription} (${t.schedule})`);
|
|
17219
|
+
lines.push(` Runs: ${t.runCount}${t.maxRuns ? `/${t.maxRuns}` : ""}${t.oneShot ? " (one-shot)" : ""}`);
|
|
17220
|
+
if (t.lastRun)
|
|
17221
|
+
lines.push(` Last run: ${t.lastRun}`);
|
|
17222
|
+
lines.push("");
|
|
17223
|
+
}
|
|
17224
|
+
}
|
|
17225
|
+
if (global.tasks.length > 0) {
|
|
17226
|
+
lines.push(`Global Tasks \u2014 shared across projects (${global.tasks.length}):
|
|
17227
|
+
`);
|
|
17228
|
+
for (const t of global.tasks) {
|
|
17229
|
+
const status = t.enabled ? "enabled" : "PAUSED";
|
|
17230
|
+
const cronInstalled = cronJobs.some((j) => j.id === t.id);
|
|
17231
|
+
const cronStatus = cronInstalled ? "" : " [cron not installed]";
|
|
17232
|
+
const isThisProject = t.projectDir === resolve22(this.workingDir);
|
|
17233
|
+
const origin = isThisProject ? " [this project]" : t.projectDir ? ` [from: ${t.projectDir}]` : "";
|
|
17234
|
+
lines.push(` [${t.id}] ${status}${cronStatus} [global]${origin}`);
|
|
17235
|
+
lines.push(` Task: ${t.task.slice(0, 100)}${t.task.length > 100 ? "..." : ""}`);
|
|
17236
|
+
lines.push(` Schedule: ${t.nextRunDescription} (${t.schedule})`);
|
|
17237
|
+
lines.push(` Runs: ${t.runCount}${t.maxRuns ? `/${t.maxRuns}` : ""}${t.oneShot ? " (one-shot)" : ""}`);
|
|
17238
|
+
if (t.lastRun)
|
|
17239
|
+
lines.push(` Last run: ${t.lastRun}`);
|
|
17240
|
+
if (!isThisProject && t.projectDir) {
|
|
17241
|
+
lines.push(` \u26A0 NOT scoped to this project \u2014 override with caution`);
|
|
17242
|
+
}
|
|
17243
|
+
lines.push("");
|
|
17244
|
+
}
|
|
17111
17245
|
}
|
|
17112
17246
|
return {
|
|
17113
17247
|
success: true,
|
|
@@ -17668,7 +17802,7 @@ ${sections.join("\n")}`,
|
|
|
17668
17802
|
const description = String(args["description"] ?? "");
|
|
17669
17803
|
const category = args["category"] ?? "followup";
|
|
17670
17804
|
const priority = args["priority"] ?? "normal";
|
|
17671
|
-
const
|
|
17805
|
+
const notes2 = args["notes"] ?? void 0;
|
|
17672
17806
|
const relatedFilesStr = args["related_files"] ?? "";
|
|
17673
17807
|
const relatedFiles = relatedFilesStr ? relatedFilesStr.split(",").map((f) => f.trim()).filter(Boolean) : void 0;
|
|
17674
17808
|
let expiresAt;
|
|
@@ -17701,7 +17835,7 @@ ${sections.join("\n")}`,
|
|
|
17701
17835
|
expiresAt,
|
|
17702
17836
|
relatedFiles,
|
|
17703
17837
|
status: "active",
|
|
17704
|
-
notes
|
|
17838
|
+
notes: notes2
|
|
17705
17839
|
};
|
|
17706
17840
|
const store = await loadAttentionStore(this.workingDir);
|
|
17707
17841
|
store.items.push(item);
|
|
@@ -18395,6 +18529,7 @@ var init_factory = __esm({
|
|
|
18395
18529
|
import { execSync as execSync21 } from "node:child_process";
|
|
18396
18530
|
import { readFile as readFile18, writeFile as writeFile18, mkdir as mkdir14 } from "node:fs/promises";
|
|
18397
18531
|
import { resolve as resolve26, join as join37 } from "node:path";
|
|
18532
|
+
import { homedir as homedir9 } from "node:os";
|
|
18398
18533
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
18399
18534
|
function isValidCron2(expr) {
|
|
18400
18535
|
const parts = expr.trim().split(/\s+/);
|
|
@@ -18523,6 +18658,31 @@ async function saveStore2(workingDir, store) {
|
|
|
18523
18658
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18524
18659
|
await writeFile18(join37(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
18525
18660
|
}
|
|
18661
|
+
function globalCronDir() {
|
|
18662
|
+
return join37(homedir9(), ".open-agents", "cron-agents");
|
|
18663
|
+
}
|
|
18664
|
+
async function loadGlobalCronStore() {
|
|
18665
|
+
try {
|
|
18666
|
+
const raw = await readFile18(join37(globalCronDir(), "store.json"), "utf-8");
|
|
18667
|
+
return JSON.parse(raw);
|
|
18668
|
+
} catch {
|
|
18669
|
+
return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
18670
|
+
}
|
|
18671
|
+
}
|
|
18672
|
+
async function saveGlobalCronStore(store) {
|
|
18673
|
+
const dir = globalCronDir();
|
|
18674
|
+
await mkdir14(dir, { recursive: true });
|
|
18675
|
+
await mkdir14(join37(dir, "logs"), { recursive: true });
|
|
18676
|
+
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18677
|
+
await writeFile18(join37(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
18678
|
+
}
|
|
18679
|
+
async function loadAllCronStores(workingDir) {
|
|
18680
|
+
const [local, global] = await Promise.all([
|
|
18681
|
+
loadStore2(workingDir),
|
|
18682
|
+
loadGlobalCronStore()
|
|
18683
|
+
]);
|
|
18684
|
+
return { local, global };
|
|
18685
|
+
}
|
|
18526
18686
|
var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
|
|
18527
18687
|
var init_cron_agent = __esm({
|
|
18528
18688
|
"packages/execution/dist/tools/cron-agent.js"() {
|
|
@@ -18591,6 +18751,11 @@ var init_cron_agent = __esm({
|
|
|
18591
18751
|
type: "array",
|
|
18592
18752
|
items: { type: "string" },
|
|
18593
18753
|
description: "Tags for organizing jobs (for 'create')"
|
|
18754
|
+
},
|
|
18755
|
+
scope: {
|
|
18756
|
+
type: "string",
|
|
18757
|
+
enum: ["local", "global"],
|
|
18758
|
+
description: "Scope: 'local' (project .oa/, default) or 'global' (~/.open-agents/, visible from all projects)"
|
|
18594
18759
|
}
|
|
18595
18760
|
},
|
|
18596
18761
|
required: ["action"]
|
|
@@ -18659,6 +18824,7 @@ var init_cron_agent = __esm({
|
|
|
18659
18824
|
const verifyCommand = args["verify_command"] ? String(args["verify_command"]) : void 0;
|
|
18660
18825
|
const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : 0;
|
|
18661
18826
|
const tags = Array.isArray(args["tags"]) ? args["tags"] : [];
|
|
18827
|
+
const scope = String(args["scope"] ?? "local");
|
|
18662
18828
|
const job = {
|
|
18663
18829
|
id,
|
|
18664
18830
|
task,
|
|
@@ -18672,11 +18838,19 @@ var init_cron_agent = __esm({
|
|
|
18672
18838
|
runCount: 0,
|
|
18673
18839
|
maxRuns,
|
|
18674
18840
|
history: [],
|
|
18675
|
-
tags
|
|
18841
|
+
tags,
|
|
18842
|
+
scope,
|
|
18843
|
+
projectDir: resolve26(this.workingDir)
|
|
18676
18844
|
};
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18845
|
+
if (scope === "global") {
|
|
18846
|
+
const store = await loadGlobalCronStore();
|
|
18847
|
+
store.jobs.push(job);
|
|
18848
|
+
await saveGlobalCronStore(store);
|
|
18849
|
+
} else {
|
|
18850
|
+
const store = await loadStore2(this.workingDir);
|
|
18851
|
+
store.jobs.push(job);
|
|
18852
|
+
await saveStore2(this.workingDir, store);
|
|
18853
|
+
}
|
|
18680
18854
|
installCronAgentJob(job, this.workingDir);
|
|
18681
18855
|
return {
|
|
18682
18856
|
success: true,
|
|
@@ -18700,19 +18874,19 @@ var init_cron_agent = __esm({
|
|
|
18700
18874
|
};
|
|
18701
18875
|
}
|
|
18702
18876
|
async listJobs(start) {
|
|
18703
|
-
const
|
|
18704
|
-
|
|
18877
|
+
const { local, global } = await loadAllCronStores(this.workingDir);
|
|
18878
|
+
const totalCount = local.jobs.length + global.jobs.length;
|
|
18879
|
+
if (totalCount === 0) {
|
|
18705
18880
|
return {
|
|
18706
18881
|
success: true,
|
|
18707
18882
|
output: "No cron agent jobs. Use cron_agent(action='create', ...) to schedule one.",
|
|
18708
18883
|
durationMs: performance.now() - start
|
|
18709
18884
|
};
|
|
18710
18885
|
}
|
|
18711
|
-
const lines = [
|
|
18712
|
-
|
|
18713
|
-
for (const job of store.jobs) {
|
|
18886
|
+
const lines = [];
|
|
18887
|
+
const formatJob = (job, scopeLabel, isThisProject) => {
|
|
18714
18888
|
const statusIcon = job.status === "active" ? "\u25CF" : job.status === "completed" ? "\u2714" : job.status === "paused" ? "\u23F8" : "\u2716";
|
|
18715
|
-
lines.push(` ${statusIcon} [${job.id}] ${job.status.toUpperCase()}`);
|
|
18889
|
+
lines.push(` ${statusIcon} [${job.id}] ${job.status.toUpperCase()} [${scopeLabel}]`);
|
|
18716
18890
|
lines.push(` Goal: ${job.goal.slice(0, 80)}${job.goal.length > 80 ? "..." : ""}`);
|
|
18717
18891
|
lines.push(` Schedule: ${job.scheduleDescription}`);
|
|
18718
18892
|
lines.push(` Runs: ${job.runCount}${job.maxRuns > 0 ? `/${job.maxRuns}` : ""}`);
|
|
@@ -18720,7 +18894,25 @@ var init_cron_agent = __esm({
|
|
|
18720
18894
|
lines.push(` Last run: ${job.lastRunAt}`);
|
|
18721
18895
|
if (job.tags.length > 0)
|
|
18722
18896
|
lines.push(` Tags: ${job.tags.join(", ")}`);
|
|
18897
|
+
if (!isThisProject && job.projectDir) {
|
|
18898
|
+
lines.push(` Origin: ${job.projectDir}`);
|
|
18899
|
+
lines.push(` \u26A0 NOT scoped to this project \u2014 override with caution`);
|
|
18900
|
+
}
|
|
18723
18901
|
lines.push("");
|
|
18902
|
+
};
|
|
18903
|
+
if (local.jobs.length > 0) {
|
|
18904
|
+
lines.push(`Local Cron Jobs \u2014 this project (${local.jobs.length}):
|
|
18905
|
+
`);
|
|
18906
|
+
for (const job of local.jobs)
|
|
18907
|
+
formatJob(job, "local", true);
|
|
18908
|
+
}
|
|
18909
|
+
if (global.jobs.length > 0) {
|
|
18910
|
+
lines.push(`Global Cron Jobs \u2014 shared (${global.jobs.length}):
|
|
18911
|
+
`);
|
|
18912
|
+
for (const job of global.jobs) {
|
|
18913
|
+
const isThisProject = job.projectDir === resolve26(this.workingDir);
|
|
18914
|
+
formatJob(job, isThisProject ? "global, this project" : "global", isThisProject);
|
|
18915
|
+
}
|
|
18724
18916
|
}
|
|
18725
18917
|
return {
|
|
18726
18918
|
success: true,
|
|
@@ -18856,6 +19048,575 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
18856
19048
|
}
|
|
18857
19049
|
});
|
|
18858
19050
|
|
|
19051
|
+
// packages/execution/dist/tools/file-explore.js
|
|
19052
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
19053
|
+
import { resolve as resolve27 } from "node:path";
|
|
19054
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
19055
|
+
import { promisify as promisify3 } from "node:util";
|
|
19056
|
+
function getPatterns(filePath) {
|
|
19057
|
+
if (/\.(ts|tsx|js|jsx|mjs|cjs)$/.test(filePath))
|
|
19058
|
+
return SIG_PATTERNS2.ts;
|
|
19059
|
+
if (/\.py$/.test(filePath))
|
|
19060
|
+
return SIG_PATTERNS2.py;
|
|
19061
|
+
if (/\.rs$/.test(filePath))
|
|
19062
|
+
return SIG_PATTERNS2.rs;
|
|
19063
|
+
if (/\.go$/.test(filePath))
|
|
19064
|
+
return SIG_PATTERNS2.go;
|
|
19065
|
+
return SIG_PATTERNS2.default;
|
|
19066
|
+
}
|
|
19067
|
+
function clearExploreNotes() {
|
|
19068
|
+
sessionNotes.length = 0;
|
|
19069
|
+
}
|
|
19070
|
+
function getExploreNotes() {
|
|
19071
|
+
return sessionNotes;
|
|
19072
|
+
}
|
|
19073
|
+
var execFileAsync3, sessionNotes, SIG_PATTERNS2, FileExploreTool;
|
|
19074
|
+
var init_file_explore = __esm({
|
|
19075
|
+
"packages/execution/dist/tools/file-explore.js"() {
|
|
19076
|
+
"use strict";
|
|
19077
|
+
execFileAsync3 = promisify3(execFile4);
|
|
19078
|
+
sessionNotes = [];
|
|
19079
|
+
SIG_PATTERNS2 = {
|
|
19080
|
+
ts: [
|
|
19081
|
+
/^\s*(export\s+)?(async\s+)?function\s+\w+/,
|
|
19082
|
+
/^\s*(export\s+)?(abstract\s+)?class\s+\w+/,
|
|
19083
|
+
/^\s*(export\s+)?(const|let|var)\s+\w+\s*[:=]/,
|
|
19084
|
+
/^\s*(export\s+)?interface\s+\w+/,
|
|
19085
|
+
/^\s*(export\s+)?type\s+\w+\s*=/,
|
|
19086
|
+
/^\s*(export\s+)?enum\s+\w+/,
|
|
19087
|
+
/^\s*(?:public|private|protected|static|async|get|set)\s+\w+\s*[(<]/
|
|
19088
|
+
],
|
|
19089
|
+
py: [
|
|
19090
|
+
/^\s*def\s+\w+/,
|
|
19091
|
+
/^\s*class\s+\w+/,
|
|
19092
|
+
/^\s*async\s+def\s+\w+/,
|
|
19093
|
+
/^[A-Z_][A-Z_0-9]*\s*=/
|
|
19094
|
+
],
|
|
19095
|
+
rs: [
|
|
19096
|
+
/^\s*(pub\s+)?(async\s+)?fn\s+\w+/,
|
|
19097
|
+
/^\s*(pub\s+)?struct\s+\w+/,
|
|
19098
|
+
/^\s*(pub\s+)?enum\s+\w+/,
|
|
19099
|
+
/^\s*(pub\s+)?trait\s+\w+/,
|
|
19100
|
+
/^\s*impl\s+/
|
|
19101
|
+
],
|
|
19102
|
+
go: [
|
|
19103
|
+
/^\s*func\s+/,
|
|
19104
|
+
/^\s*type\s+\w+\s+struct/,
|
|
19105
|
+
/^\s*type\s+\w+\s+interface/
|
|
19106
|
+
],
|
|
19107
|
+
default: [
|
|
19108
|
+
/^\s*(export\s+)?(function|class|const|let|var|def|fn|pub|type|interface|enum|struct|trait|impl)\s+/
|
|
19109
|
+
]
|
|
19110
|
+
};
|
|
19111
|
+
FileExploreTool = class {
|
|
19112
|
+
name = "file_explore";
|
|
19113
|
+
description = "Explore large files without reading them entirely into context. Strategies: 'overview' (structural skeleton \u2014 imports, exports, signatures), 'search' (grep pattern with \xB1N context lines), 'chunk' (read specific line range, auto-saved to working notes), 'outline' (function/class/method signatures only), 'notes' (show accumulated findings from this session). Use this INSTEAD of file_read for files > 200 lines. Pattern: overview \u2192 search for target \u2192 chunk to read details \u2192 note findings.";
|
|
19114
|
+
parameters = {
|
|
19115
|
+
type: "object",
|
|
19116
|
+
properties: {
|
|
19117
|
+
path: {
|
|
19118
|
+
type: "string",
|
|
19119
|
+
description: "File path to explore"
|
|
19120
|
+
},
|
|
19121
|
+
strategy: {
|
|
19122
|
+
type: "string",
|
|
19123
|
+
enum: ["overview", "search", "chunk", "outline", "notes"],
|
|
19124
|
+
description: "Exploration strategy"
|
|
19125
|
+
},
|
|
19126
|
+
query: {
|
|
19127
|
+
type: "string",
|
|
19128
|
+
description: "Search pattern (for 'search' strategy) or note text (for 'chunk' with note)"
|
|
19129
|
+
},
|
|
19130
|
+
offset: {
|
|
19131
|
+
type: "number",
|
|
19132
|
+
description: "Starting line number, 1-based (for 'chunk' strategy)"
|
|
19133
|
+
},
|
|
19134
|
+
limit: {
|
|
19135
|
+
type: "number",
|
|
19136
|
+
description: "Number of lines to read (for 'chunk', default 50)"
|
|
19137
|
+
},
|
|
19138
|
+
context_lines: {
|
|
19139
|
+
type: "number",
|
|
19140
|
+
description: "Lines of context around each match (for 'search', default 5)"
|
|
19141
|
+
},
|
|
19142
|
+
note: {
|
|
19143
|
+
type: "string",
|
|
19144
|
+
description: "Working note to save about this chunk (for 'chunk' strategy)"
|
|
19145
|
+
}
|
|
19146
|
+
},
|
|
19147
|
+
required: ["strategy"]
|
|
19148
|
+
};
|
|
19149
|
+
workingDir;
|
|
19150
|
+
constructor(workingDir) {
|
|
19151
|
+
this.workingDir = workingDir;
|
|
19152
|
+
}
|
|
19153
|
+
async execute(args) {
|
|
19154
|
+
const strategy = String(args["strategy"] ?? "overview");
|
|
19155
|
+
const filePath = String(args["path"] ?? "");
|
|
19156
|
+
const start = performance.now();
|
|
19157
|
+
switch (strategy) {
|
|
19158
|
+
case "overview":
|
|
19159
|
+
return this.overview(filePath, start);
|
|
19160
|
+
case "search":
|
|
19161
|
+
return this.search(filePath, String(args["query"] ?? ""), args, start);
|
|
19162
|
+
case "chunk":
|
|
19163
|
+
return this.chunk(filePath, args, start);
|
|
19164
|
+
case "outline":
|
|
19165
|
+
return this.outline(filePath, start);
|
|
19166
|
+
case "notes":
|
|
19167
|
+
return this.showNotes(filePath, start);
|
|
19168
|
+
default:
|
|
19169
|
+
return {
|
|
19170
|
+
success: false,
|
|
19171
|
+
output: "",
|
|
19172
|
+
error: `Unknown strategy '${strategy}'. Use: overview, search, chunk, outline, notes`,
|
|
19173
|
+
durationMs: performance.now() - start
|
|
19174
|
+
};
|
|
19175
|
+
}
|
|
19176
|
+
}
|
|
19177
|
+
/**
|
|
19178
|
+
* overview: Read structural skeleton — first 30 lines (imports/config),
|
|
19179
|
+
* all signature lines, last 20 lines (exports/module boundary).
|
|
19180
|
+
*/
|
|
19181
|
+
async overview(filePath, start) {
|
|
19182
|
+
if (!filePath)
|
|
19183
|
+
return { success: false, output: "", error: "path required for overview", durationMs: performance.now() - start };
|
|
19184
|
+
try {
|
|
19185
|
+
const fullPath = resolve27(this.workingDir, filePath);
|
|
19186
|
+
const content = await readFile19(fullPath, "utf-8");
|
|
19187
|
+
const lines = content.split("\n");
|
|
19188
|
+
const total = lines.length;
|
|
19189
|
+
const HEAD = Math.min(30, total);
|
|
19190
|
+
const TAIL = Math.min(20, Math.max(0, total - HEAD));
|
|
19191
|
+
const parts = [];
|
|
19192
|
+
parts.push(`# ${filePath} (${total} lines)
|
|
19193
|
+
`);
|
|
19194
|
+
parts.push("## Head (lines 1-" + HEAD + ")");
|
|
19195
|
+
for (let i = 0; i < HEAD; i++) {
|
|
19196
|
+
parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
|
|
19197
|
+
}
|
|
19198
|
+
if (total > HEAD + TAIL) {
|
|
19199
|
+
const patterns = getPatterns(filePath);
|
|
19200
|
+
const sigs = [];
|
|
19201
|
+
for (let i = HEAD; i < total - TAIL; i++) {
|
|
19202
|
+
const line = lines[i];
|
|
19203
|
+
if (patterns.some((p) => p.test(line))) {
|
|
19204
|
+
sigs.push(`${String(i + 1).padStart(6)} | ${line}`);
|
|
19205
|
+
}
|
|
19206
|
+
}
|
|
19207
|
+
if (sigs.length > 0) {
|
|
19208
|
+
parts.push(`
|
|
19209
|
+
## Signatures (lines ${HEAD + 1}-${total - TAIL}) \u2014 ${sigs.length} found`);
|
|
19210
|
+
parts.push(...sigs);
|
|
19211
|
+
} else {
|
|
19212
|
+
parts.push(`
|
|
19213
|
+
## Middle (lines ${HEAD + 1}-${total - TAIL}) \u2014 ${total - HEAD - TAIL} lines, no signatures detected`);
|
|
19214
|
+
}
|
|
19215
|
+
}
|
|
19216
|
+
if (TAIL > 0) {
|
|
19217
|
+
const tailStart = total - TAIL;
|
|
19218
|
+
parts.push(`
|
|
19219
|
+
## Tail (lines ${tailStart + 1}-${total})`);
|
|
19220
|
+
for (let i = tailStart; i < total; i++) {
|
|
19221
|
+
parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
|
|
19222
|
+
}
|
|
19223
|
+
}
|
|
19224
|
+
parts.push(`
|
|
19225
|
+
[Use file_explore(strategy='search', query='...') to find specific sections]`);
|
|
19226
|
+
parts.push(`[Use file_explore(strategy='chunk', offset=N, limit=50) to read a section]`);
|
|
19227
|
+
return {
|
|
19228
|
+
success: true,
|
|
19229
|
+
output: parts.join("\n"),
|
|
19230
|
+
durationMs: performance.now() - start
|
|
19231
|
+
};
|
|
19232
|
+
} catch (error) {
|
|
19233
|
+
return {
|
|
19234
|
+
success: false,
|
|
19235
|
+
output: "",
|
|
19236
|
+
error: error instanceof Error ? error.message : String(error),
|
|
19237
|
+
durationMs: performance.now() - start
|
|
19238
|
+
};
|
|
19239
|
+
}
|
|
19240
|
+
}
|
|
19241
|
+
/**
|
|
19242
|
+
* search: Grep for pattern with context lines around each match.
|
|
19243
|
+
*/
|
|
19244
|
+
async search(filePath, query, args, start) {
|
|
19245
|
+
if (!query)
|
|
19246
|
+
return { success: false, output: "", error: "query required for search strategy", durationMs: performance.now() - start };
|
|
19247
|
+
const contextLines = Number(args["context_lines"] ?? 5);
|
|
19248
|
+
const searchPath = filePath ? resolve27(this.workingDir, filePath) : this.workingDir;
|
|
19249
|
+
try {
|
|
19250
|
+
const rgArgs = [
|
|
19251
|
+
"--line-number",
|
|
19252
|
+
"--no-heading",
|
|
19253
|
+
"--color=never",
|
|
19254
|
+
"-C",
|
|
19255
|
+
String(contextLines)
|
|
19256
|
+
];
|
|
19257
|
+
if (filePath) {
|
|
19258
|
+
rgArgs.push(query, searchPath);
|
|
19259
|
+
} else {
|
|
19260
|
+
rgArgs.push(query, this.workingDir);
|
|
19261
|
+
}
|
|
19262
|
+
const { stdout } = await execFileAsync3("rg", rgArgs, {
|
|
19263
|
+
cwd: this.workingDir,
|
|
19264
|
+
maxBuffer: 1024 * 1024
|
|
19265
|
+
});
|
|
19266
|
+
const lines = stdout.split("\n").filter((l) => l.length > 0);
|
|
19267
|
+
const matchCount = lines.filter((l) => /^\d+:/.test(l) || /:\d+:/.test(l)).length;
|
|
19268
|
+
const MAX = 80;
|
|
19269
|
+
const truncated = lines.length > MAX;
|
|
19270
|
+
const output = lines.slice(0, MAX).join("\n");
|
|
19271
|
+
const result = [
|
|
19272
|
+
`Found ${matchCount} matches for "${query}"${filePath ? ` in ${filePath}` : ""}:`,
|
|
19273
|
+
"",
|
|
19274
|
+
truncated ? output + `
|
|
19275
|
+
|
|
19276
|
+
[Truncated \u2014 ${lines.length - MAX} more lines]` : output,
|
|
19277
|
+
"",
|
|
19278
|
+
`[Use file_explore(strategy='chunk', path='...', offset=N) to read around a specific match]`
|
|
19279
|
+
].join("\n");
|
|
19280
|
+
return {
|
|
19281
|
+
success: true,
|
|
19282
|
+
output: result,
|
|
19283
|
+
durationMs: performance.now() - start
|
|
19284
|
+
};
|
|
19285
|
+
} catch (error) {
|
|
19286
|
+
const err = error;
|
|
19287
|
+
if (err.code === 1) {
|
|
19288
|
+
return {
|
|
19289
|
+
success: true,
|
|
19290
|
+
output: `No matches for "${query}"${filePath ? ` in ${filePath}` : ""}.`,
|
|
19291
|
+
durationMs: performance.now() - start
|
|
19292
|
+
};
|
|
19293
|
+
}
|
|
19294
|
+
try {
|
|
19295
|
+
const grepArgs = ["-rn", "--color=never", `-C${contextLines}`];
|
|
19296
|
+
if (filePath) {
|
|
19297
|
+
grepArgs.push(query, searchPath);
|
|
19298
|
+
} else {
|
|
19299
|
+
grepArgs.push(query, this.workingDir);
|
|
19300
|
+
}
|
|
19301
|
+
const { stdout } = await execFileAsync3("grep", grepArgs, {
|
|
19302
|
+
cwd: this.workingDir,
|
|
19303
|
+
maxBuffer: 1024 * 1024
|
|
19304
|
+
});
|
|
19305
|
+
return {
|
|
19306
|
+
success: true,
|
|
19307
|
+
output: stdout.split("\n").slice(0, 80).join("\n"),
|
|
19308
|
+
durationMs: performance.now() - start
|
|
19309
|
+
};
|
|
19310
|
+
} catch {
|
|
19311
|
+
return {
|
|
19312
|
+
success: true,
|
|
19313
|
+
output: `No matches for "${query}".`,
|
|
19314
|
+
durationMs: performance.now() - start
|
|
19315
|
+
};
|
|
19316
|
+
}
|
|
19317
|
+
}
|
|
19318
|
+
}
|
|
19319
|
+
/**
|
|
19320
|
+
* chunk: Read a specific line range and optionally save a working note.
|
|
19321
|
+
*/
|
|
19322
|
+
async chunk(filePath, args, start) {
|
|
19323
|
+
if (!filePath)
|
|
19324
|
+
return { success: false, output: "", error: "path required for chunk strategy", durationMs: performance.now() - start };
|
|
19325
|
+
const offset = Number(args["offset"] ?? 1);
|
|
19326
|
+
const limit = Number(args["limit"] ?? 50);
|
|
19327
|
+
const note = args["note"];
|
|
19328
|
+
try {
|
|
19329
|
+
const fullPath = resolve27(this.workingDir, filePath);
|
|
19330
|
+
const content = await readFile19(fullPath, "utf-8");
|
|
19331
|
+
const allLines = content.split("\n");
|
|
19332
|
+
const total = allLines.length;
|
|
19333
|
+
const startIdx = Math.max(0, offset - 1);
|
|
19334
|
+
const endIdx = Math.min(total, startIdx + limit);
|
|
19335
|
+
const chunk = allLines.slice(startIdx, endIdx);
|
|
19336
|
+
const numbered = chunk.map((line, i) => `${String(startIdx + i + 1).padStart(6)} | ${line}`).join("\n");
|
|
19337
|
+
if (note) {
|
|
19338
|
+
sessionNotes.push({
|
|
19339
|
+
file: filePath,
|
|
19340
|
+
lineRange: [startIdx + 1, endIdx],
|
|
19341
|
+
finding: note,
|
|
19342
|
+
timestamp: Date.now()
|
|
19343
|
+
});
|
|
19344
|
+
}
|
|
19345
|
+
const nav = [];
|
|
19346
|
+
if (startIdx > 0) {
|
|
19347
|
+
nav.push(`[Previous: file_explore(strategy='chunk', path='${filePath}', offset=${Math.max(1, startIdx + 1 - limit)}, limit=${limit})]`);
|
|
19348
|
+
}
|
|
19349
|
+
if (endIdx < total) {
|
|
19350
|
+
nav.push(`[Next: file_explore(strategy='chunk', path='${filePath}', offset=${endIdx + 1}, limit=${limit})]`);
|
|
19351
|
+
}
|
|
19352
|
+
nav.push(`[${total} total lines \u2014 showing ${startIdx + 1}-${endIdx}]`);
|
|
19353
|
+
if (sessionNotes.length > 0) {
|
|
19354
|
+
nav.push(`[${sessionNotes.length} working notes \u2014 file_explore(strategy='notes') to review]`);
|
|
19355
|
+
}
|
|
19356
|
+
return {
|
|
19357
|
+
success: true,
|
|
19358
|
+
output: numbered + "\n\n" + nav.join("\n"),
|
|
19359
|
+
durationMs: performance.now() - start
|
|
19360
|
+
};
|
|
19361
|
+
} catch (error) {
|
|
19362
|
+
return {
|
|
19363
|
+
success: false,
|
|
19364
|
+
output: "",
|
|
19365
|
+
error: error instanceof Error ? error.message : String(error),
|
|
19366
|
+
durationMs: performance.now() - start
|
|
19367
|
+
};
|
|
19368
|
+
}
|
|
19369
|
+
}
|
|
19370
|
+
/**
|
|
19371
|
+
* outline: Extract only function/class/method/export signatures.
|
|
19372
|
+
*/
|
|
19373
|
+
async outline(filePath, start) {
|
|
19374
|
+
if (!filePath)
|
|
19375
|
+
return { success: false, output: "", error: "path required for outline", durationMs: performance.now() - start };
|
|
19376
|
+
try {
|
|
19377
|
+
const fullPath = resolve27(this.workingDir, filePath);
|
|
19378
|
+
const content = await readFile19(fullPath, "utf-8");
|
|
19379
|
+
const lines = content.split("\n");
|
|
19380
|
+
const patterns = getPatterns(filePath);
|
|
19381
|
+
const sigs = [];
|
|
19382
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19383
|
+
const line = lines[i];
|
|
19384
|
+
if (patterns.some((p) => p.test(line))) {
|
|
19385
|
+
sigs.push(`${String(i + 1).padStart(6)} | ${line.trimEnd()}`);
|
|
19386
|
+
}
|
|
19387
|
+
}
|
|
19388
|
+
if (sigs.length === 0) {
|
|
19389
|
+
return {
|
|
19390
|
+
success: true,
|
|
19391
|
+
output: `${filePath}: ${lines.length} lines, no recognizable signatures found.
|
|
19392
|
+
[Use file_explore(strategy='overview') for a broader view]`,
|
|
19393
|
+
durationMs: performance.now() - start
|
|
19394
|
+
};
|
|
19395
|
+
}
|
|
19396
|
+
return {
|
|
19397
|
+
success: true,
|
|
19398
|
+
output: `# ${filePath} \u2014 ${sigs.length} signatures (${lines.length} total lines)
|
|
19399
|
+
|
|
19400
|
+
` + sigs.join("\n") + `
|
|
19401
|
+
|
|
19402
|
+
[Use file_explore(strategy='chunk', offset=N) to read around a specific signature]`,
|
|
19403
|
+
durationMs: performance.now() - start
|
|
19404
|
+
};
|
|
19405
|
+
} catch (error) {
|
|
19406
|
+
return {
|
|
19407
|
+
success: false,
|
|
19408
|
+
output: "",
|
|
19409
|
+
error: error instanceof Error ? error.message : String(error),
|
|
19410
|
+
durationMs: performance.now() - start
|
|
19411
|
+
};
|
|
19412
|
+
}
|
|
19413
|
+
}
|
|
19414
|
+
/**
|
|
19415
|
+
* notes: Show accumulated working notes from this exploration session.
|
|
19416
|
+
*/
|
|
19417
|
+
showNotes(filePath, start) {
|
|
19418
|
+
const notes2 = filePath ? sessionNotes.filter((n) => n.file === filePath) : sessionNotes;
|
|
19419
|
+
if (notes2.length === 0) {
|
|
19420
|
+
return {
|
|
19421
|
+
success: true,
|
|
19422
|
+
output: "No working notes yet. Use file_explore(strategy='chunk', note='your finding') to save notes as you explore.",
|
|
19423
|
+
durationMs: performance.now() - start
|
|
19424
|
+
};
|
|
19425
|
+
}
|
|
19426
|
+
const parts = [`# Working Notes (${notes2.length})
|
|
19427
|
+
`];
|
|
19428
|
+
for (const n of notes2) {
|
|
19429
|
+
parts.push(`- **${n.file}** lines ${n.lineRange[0]}-${n.lineRange[1]}: ${n.finding}`);
|
|
19430
|
+
}
|
|
19431
|
+
return {
|
|
19432
|
+
success: true,
|
|
19433
|
+
output: parts.join("\n"),
|
|
19434
|
+
durationMs: performance.now() - start
|
|
19435
|
+
};
|
|
19436
|
+
}
|
|
19437
|
+
};
|
|
19438
|
+
}
|
|
19439
|
+
});
|
|
19440
|
+
|
|
19441
|
+
// packages/execution/dist/tools/working-notes.js
|
|
19442
|
+
function getWorkingNotes() {
|
|
19443
|
+
return notes;
|
|
19444
|
+
}
|
|
19445
|
+
function getWorkingNotesSummary() {
|
|
19446
|
+
if (notes.length === 0)
|
|
19447
|
+
return "";
|
|
19448
|
+
const parts = [`Working notes (${notes.length}):`];
|
|
19449
|
+
for (const n of notes) {
|
|
19450
|
+
const loc = n.file ? ` [${n.file}${n.line ? `:${n.line}` : ""}]` : "";
|
|
19451
|
+
parts.push(`- [${n.category}] ${n.content.slice(0, 150)}${loc}`);
|
|
19452
|
+
}
|
|
19453
|
+
return parts.join("\n");
|
|
19454
|
+
}
|
|
19455
|
+
function clearWorkingNotes() {
|
|
19456
|
+
notes.length = 0;
|
|
19457
|
+
noteCounter = 0;
|
|
19458
|
+
}
|
|
19459
|
+
var noteCounter, notes, WorkingNotesTool;
|
|
19460
|
+
var init_working_notes = __esm({
|
|
19461
|
+
"packages/execution/dist/tools/working-notes.js"() {
|
|
19462
|
+
"use strict";
|
|
19463
|
+
noteCounter = 0;
|
|
19464
|
+
notes = [];
|
|
19465
|
+
WorkingNotesTool = class {
|
|
19466
|
+
name = "working_notes";
|
|
19467
|
+
description = "In-task scratchpad for tracking discoveries, decisions, and TODOs. Notes persist across tool calls and survive context compaction. Actions: 'add' a note, 'list' all notes, 'search' notes by keyword, 'clear' all notes, 'summary' get a compact summary. Use this to maintain signal when exploring large codebases \u2014 note findings as you go so you don't lose them to context limits.";
|
|
19468
|
+
parameters = {
|
|
19469
|
+
type: "object",
|
|
19470
|
+
properties: {
|
|
19471
|
+
action: {
|
|
19472
|
+
type: "string",
|
|
19473
|
+
enum: ["add", "list", "search", "clear", "summary"],
|
|
19474
|
+
description: "Action to perform (default: 'list')"
|
|
19475
|
+
},
|
|
19476
|
+
content: {
|
|
19477
|
+
type: "string",
|
|
19478
|
+
description: "Note content (for 'add') or search query (for 'search')"
|
|
19479
|
+
},
|
|
19480
|
+
category: {
|
|
19481
|
+
type: "string",
|
|
19482
|
+
enum: ["finding", "todo", "question", "decision", "blocker"],
|
|
19483
|
+
description: "Note category (for 'add', default: 'finding')"
|
|
19484
|
+
},
|
|
19485
|
+
file: {
|
|
19486
|
+
type: "string",
|
|
19487
|
+
description: "Related file path (for 'add')"
|
|
19488
|
+
},
|
|
19489
|
+
line: {
|
|
19490
|
+
type: "number",
|
|
19491
|
+
description: "Related line number (for 'add')"
|
|
19492
|
+
}
|
|
19493
|
+
},
|
|
19494
|
+
required: []
|
|
19495
|
+
};
|
|
19496
|
+
async execute(args) {
|
|
19497
|
+
const action = String(args["action"] ?? "list");
|
|
19498
|
+
const start = performance.now();
|
|
19499
|
+
switch (action) {
|
|
19500
|
+
case "add": {
|
|
19501
|
+
const content = String(args["content"] ?? "");
|
|
19502
|
+
if (!content)
|
|
19503
|
+
return { success: false, output: "", error: "content required", durationMs: performance.now() - start };
|
|
19504
|
+
const note = {
|
|
19505
|
+
id: ++noteCounter,
|
|
19506
|
+
category: String(args["category"] ?? "finding"),
|
|
19507
|
+
content,
|
|
19508
|
+
file: args["file"],
|
|
19509
|
+
line: args["line"],
|
|
19510
|
+
timestamp: Date.now()
|
|
19511
|
+
};
|
|
19512
|
+
notes.push(note);
|
|
19513
|
+
return {
|
|
19514
|
+
success: true,
|
|
19515
|
+
output: `Note #${note.id} added [${note.category}]${note.file ? ` (${note.file}${note.line ? `:${note.line}` : ""})` : ""}: ${content.slice(0, 100)}`,
|
|
19516
|
+
durationMs: performance.now() - start
|
|
19517
|
+
};
|
|
19518
|
+
}
|
|
19519
|
+
case "list": {
|
|
19520
|
+
if (notes.length === 0) {
|
|
19521
|
+
return {
|
|
19522
|
+
success: true,
|
|
19523
|
+
output: "No working notes. Use working_notes(action='add', content='...') to start tracking findings.",
|
|
19524
|
+
durationMs: performance.now() - start
|
|
19525
|
+
};
|
|
19526
|
+
}
|
|
19527
|
+
const lines = [`Working Notes (${notes.length}):
|
|
19528
|
+
`];
|
|
19529
|
+
for (const n of notes) {
|
|
19530
|
+
const loc = n.file ? ` @ ${n.file}${n.line ? `:${n.line}` : ""}` : "";
|
|
19531
|
+
lines.push(` #${n.id} [${n.category}]${loc}: ${n.content}`);
|
|
19532
|
+
}
|
|
19533
|
+
return {
|
|
19534
|
+
success: true,
|
|
19535
|
+
output: lines.join("\n"),
|
|
19536
|
+
durationMs: performance.now() - start
|
|
19537
|
+
};
|
|
19538
|
+
}
|
|
19539
|
+
case "search": {
|
|
19540
|
+
const query = String(args["content"] ?? "").toLowerCase();
|
|
19541
|
+
if (!query)
|
|
19542
|
+
return { success: false, output: "", error: "content (search query) required", durationMs: performance.now() - start };
|
|
19543
|
+
const matches = notes.filter((n) => n.content.toLowerCase().includes(query) || n.file && n.file.toLowerCase().includes(query) || n.category.toLowerCase().includes(query));
|
|
19544
|
+
if (matches.length === 0) {
|
|
19545
|
+
return {
|
|
19546
|
+
success: true,
|
|
19547
|
+
output: `No notes matching "${query}".`,
|
|
19548
|
+
durationMs: performance.now() - start
|
|
19549
|
+
};
|
|
19550
|
+
}
|
|
19551
|
+
const lines = [`Notes matching "${query}" (${matches.length}):
|
|
19552
|
+
`];
|
|
19553
|
+
for (const n of matches) {
|
|
19554
|
+
const loc = n.file ? ` @ ${n.file}${n.line ? `:${n.line}` : ""}` : "";
|
|
19555
|
+
lines.push(` #${n.id} [${n.category}]${loc}: ${n.content}`);
|
|
19556
|
+
}
|
|
19557
|
+
return {
|
|
19558
|
+
success: true,
|
|
19559
|
+
output: lines.join("\n"),
|
|
19560
|
+
durationMs: performance.now() - start
|
|
19561
|
+
};
|
|
19562
|
+
}
|
|
19563
|
+
case "clear": {
|
|
19564
|
+
const count = notes.length;
|
|
19565
|
+
notes.length = 0;
|
|
19566
|
+
noteCounter = 0;
|
|
19567
|
+
return {
|
|
19568
|
+
success: true,
|
|
19569
|
+
output: `Cleared ${count} working notes.`,
|
|
19570
|
+
durationMs: performance.now() - start
|
|
19571
|
+
};
|
|
19572
|
+
}
|
|
19573
|
+
case "summary": {
|
|
19574
|
+
if (notes.length === 0) {
|
|
19575
|
+
return {
|
|
19576
|
+
success: true,
|
|
19577
|
+
output: "No working notes to summarize.",
|
|
19578
|
+
durationMs: performance.now() - start
|
|
19579
|
+
};
|
|
19580
|
+
}
|
|
19581
|
+
const groups = /* @__PURE__ */ new Map();
|
|
19582
|
+
for (const n of notes) {
|
|
19583
|
+
const list = groups.get(n.category) ?? [];
|
|
19584
|
+
list.push(n);
|
|
19585
|
+
groups.set(n.category, list);
|
|
19586
|
+
}
|
|
19587
|
+
const parts = [`Working Notes Summary (${notes.length} total):
|
|
19588
|
+
`];
|
|
19589
|
+
for (const [cat, items] of groups) {
|
|
19590
|
+
parts.push(` ${cat.toUpperCase()} (${items.length}):`);
|
|
19591
|
+
for (const n of items) {
|
|
19592
|
+
const loc = n.file ? ` [${n.file}${n.line ? `:${n.line}` : ""}]` : "";
|
|
19593
|
+
parts.push(` - ${n.content.slice(0, 120)}${loc}`);
|
|
19594
|
+
}
|
|
19595
|
+
}
|
|
19596
|
+
const files = new Set(notes.filter((n) => n.file).map((n) => n.file));
|
|
19597
|
+
if (files.size > 0) {
|
|
19598
|
+
parts.push(`
|
|
19599
|
+
Files referenced: ${[...files].join(", ")}`);
|
|
19600
|
+
}
|
|
19601
|
+
return {
|
|
19602
|
+
success: true,
|
|
19603
|
+
output: parts.join("\n"),
|
|
19604
|
+
durationMs: performance.now() - start
|
|
19605
|
+
};
|
|
19606
|
+
}
|
|
19607
|
+
default:
|
|
19608
|
+
return {
|
|
19609
|
+
success: false,
|
|
19610
|
+
output: "",
|
|
19611
|
+
error: `Unknown action '${action}'. Use: add, list, search, clear, summary`,
|
|
19612
|
+
durationMs: performance.now() - start
|
|
19613
|
+
};
|
|
19614
|
+
}
|
|
19615
|
+
}
|
|
19616
|
+
};
|
|
19617
|
+
}
|
|
19618
|
+
});
|
|
19619
|
+
|
|
18859
19620
|
// packages/execution/dist/tools/fortemi-bridge.js
|
|
18860
19621
|
import { existsSync as existsSync24, readFileSync as readFileSync17 } from "node:fs";
|
|
18861
19622
|
import { join as join38 } from "node:path";
|
|
@@ -19012,7 +19773,7 @@ import { spawn as spawn13 } from "node:child_process";
|
|
|
19012
19773
|
async function runShell(options) {
|
|
19013
19774
|
const { command, args = [], cwd: cwd4, env, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
|
|
19014
19775
|
const mergedEnv = env ? { ...process.env, ...env } : process.env;
|
|
19015
|
-
return new Promise((
|
|
19776
|
+
return new Promise((resolve33) => {
|
|
19016
19777
|
const start = Date.now();
|
|
19017
19778
|
let timedOut = false;
|
|
19018
19779
|
const child = spawn13(command, args, {
|
|
@@ -19036,7 +19797,7 @@ async function runShell(options) {
|
|
|
19036
19797
|
clearTimeout(timer);
|
|
19037
19798
|
const durationMs = Date.now() - start;
|
|
19038
19799
|
const exitCode = timedOut ? -1 : code ?? -1;
|
|
19039
|
-
|
|
19800
|
+
resolve33({
|
|
19040
19801
|
stdout,
|
|
19041
19802
|
stderr,
|
|
19042
19803
|
exitCode,
|
|
@@ -19048,7 +19809,7 @@ async function runShell(options) {
|
|
|
19048
19809
|
child.on("error", (err) => {
|
|
19049
19810
|
clearTimeout(timer);
|
|
19050
19811
|
const durationMs = Date.now() - start;
|
|
19051
|
-
|
|
19812
|
+
resolve33({
|
|
19052
19813
|
stdout,
|
|
19053
19814
|
stderr: stderr + err.message,
|
|
19054
19815
|
exitCode: -1,
|
|
@@ -19163,7 +19924,7 @@ async function applyUnifiedDiff(patch) {
|
|
|
19163
19924
|
}
|
|
19164
19925
|
function runWithStdin(options) {
|
|
19165
19926
|
const { command, args, cwd: cwd4, stdin } = options;
|
|
19166
|
-
return new Promise((
|
|
19927
|
+
return new Promise((resolve33) => {
|
|
19167
19928
|
const child = spawn14(command, args, {
|
|
19168
19929
|
cwd: cwd4,
|
|
19169
19930
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -19180,10 +19941,10 @@ function runWithStdin(options) {
|
|
|
19180
19941
|
child.stdin.end();
|
|
19181
19942
|
child.on("close", (code) => {
|
|
19182
19943
|
const exitCode = code ?? -1;
|
|
19183
|
-
|
|
19944
|
+
resolve33({ success: exitCode === 0, exitCode, stdout, stderr });
|
|
19184
19945
|
});
|
|
19185
19946
|
child.on("error", (err) => {
|
|
19186
|
-
|
|
19947
|
+
resolve33({ success: false, exitCode: -1, stdout, stderr: err.message });
|
|
19187
19948
|
});
|
|
19188
19949
|
});
|
|
19189
19950
|
}
|
|
@@ -19631,6 +20392,7 @@ __export(dist_exports, {
|
|
|
19631
20392
|
ExploreToolsTool: () => ExploreToolsTool,
|
|
19632
20393
|
FactoryTool: () => FactoryTool,
|
|
19633
20394
|
FileEditTool: () => FileEditTool,
|
|
20395
|
+
FileExploreTool: () => FileExploreTool,
|
|
19634
20396
|
FilePatchTool: () => FilePatchTool,
|
|
19635
20397
|
FileReadTool: () => FileReadTool,
|
|
19636
20398
|
FileWriteTool: () => FileWriteTool,
|
|
@@ -19673,10 +20435,13 @@ __export(dist_exports, {
|
|
|
19673
20435
|
WebCrawlTool: () => WebCrawlTool,
|
|
19674
20436
|
WebFetchTool: () => WebFetchTool,
|
|
19675
20437
|
WebSearchTool: () => WebSearchTool,
|
|
20438
|
+
WorkingNotesTool: () => WorkingNotesTool,
|
|
19676
20439
|
applyPatch: () => applyPatch,
|
|
19677
20440
|
buildCustomTools: () => buildCustomTools,
|
|
19678
20441
|
buildSkillsSummary: () => buildSkillsSummary,
|
|
19679
20442
|
checkDesktopDeps: () => checkDesktopDeps,
|
|
20443
|
+
clearExploreNotes: () => clearExploreNotes,
|
|
20444
|
+
clearWorkingNotes: () => clearWorkingNotes,
|
|
19680
20445
|
createFortemiBridgeTools: () => createFortemiBridgeTools,
|
|
19681
20446
|
createWorktree: () => createWorktree,
|
|
19682
20447
|
detectSearchProvider: () => detectSearchProvider,
|
|
@@ -19686,6 +20451,9 @@ __export(dist_exports, {
|
|
|
19686
20451
|
ensureDepsForGroup: () => ensureDepsForGroup,
|
|
19687
20452
|
getActiveAttentionItems: () => getActiveAttentionItems,
|
|
19688
20453
|
getDueReminders: () => getDueReminders,
|
|
20454
|
+
getExploreNotes: () => getExploreNotes,
|
|
20455
|
+
getWorkingNotes: () => getWorkingNotes,
|
|
20456
|
+
getWorkingNotesSummary: () => getWorkingNotesSummary,
|
|
19689
20457
|
isFortemiAvailable: () => isFortemiAvailable,
|
|
19690
20458
|
isImagePath: () => isImagePath,
|
|
19691
20459
|
listCustomToolFiles: () => listCustomToolFiles,
|
|
@@ -19762,6 +20530,8 @@ var init_dist2 = __esm({
|
|
|
19762
20530
|
init_opencode();
|
|
19763
20531
|
init_factory();
|
|
19764
20532
|
init_cron_agent();
|
|
20533
|
+
init_file_explore();
|
|
20534
|
+
init_working_notes();
|
|
19765
20535
|
init_nexus();
|
|
19766
20536
|
init_fortemi_bridge();
|
|
19767
20537
|
init_system_deps();
|
|
@@ -20745,13 +21515,13 @@ var init_plannerRunner = __esm({
|
|
|
20745
21515
|
});
|
|
20746
21516
|
|
|
20747
21517
|
// packages/retrieval/dist/grep-search.js
|
|
20748
|
-
import { execFile as
|
|
20749
|
-
import { promisify as
|
|
20750
|
-
var
|
|
21518
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
21519
|
+
import { promisify as promisify4 } from "node:util";
|
|
21520
|
+
var execFileAsync4, GrepSearch;
|
|
20751
21521
|
var init_grep_search2 = __esm({
|
|
20752
21522
|
"packages/retrieval/dist/grep-search.js"() {
|
|
20753
21523
|
"use strict";
|
|
20754
|
-
|
|
21524
|
+
execFileAsync4 = promisify4(execFile5);
|
|
20755
21525
|
GrepSearch = class {
|
|
20756
21526
|
rootDir;
|
|
20757
21527
|
constructor(rootDir) {
|
|
@@ -20773,7 +21543,7 @@ var init_grep_search2 = __esm({
|
|
|
20773
21543
|
}
|
|
20774
21544
|
args.push(pattern, this.rootDir);
|
|
20775
21545
|
try {
|
|
20776
|
-
const { stdout } = await
|
|
21546
|
+
const { stdout } = await execFileAsync4("rg", args, {
|
|
20777
21547
|
maxBuffer: 10 * 1024 * 1024
|
|
20778
21548
|
});
|
|
20779
21549
|
return this.parseRipgrepOutput(stdout);
|
|
@@ -20834,8 +21604,8 @@ var init_code_retriever = __esm({
|
|
|
20834
21604
|
});
|
|
20835
21605
|
}
|
|
20836
21606
|
async getFileContent(filePath, startLine, endLine) {
|
|
20837
|
-
const { readFile:
|
|
20838
|
-
const content = await
|
|
21607
|
+
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
21608
|
+
const content = await readFile24(filePath, "utf-8");
|
|
20839
21609
|
if (startLine === void 0)
|
|
20840
21610
|
return content;
|
|
20841
21611
|
const lines = content.split("\n");
|
|
@@ -20848,9 +21618,9 @@ var init_code_retriever = __esm({
|
|
|
20848
21618
|
});
|
|
20849
21619
|
|
|
20850
21620
|
// packages/retrieval/dist/lexicalSearch.js
|
|
20851
|
-
import { execFile as
|
|
20852
|
-
import { promisify as
|
|
20853
|
-
import { readFile as
|
|
21621
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
21622
|
+
import { promisify as promisify5 } from "node:util";
|
|
21623
|
+
import { readFile as readFile20, readdir as readdir5, stat as stat3 } from "node:fs/promises";
|
|
20854
21624
|
import { join as join40, extname as extname7 } from "node:path";
|
|
20855
21625
|
async function searchByPath(pathPattern, options) {
|
|
20856
21626
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
@@ -20893,7 +21663,7 @@ async function runSearch(pattern, kind, options) {
|
|
|
20893
21663
|
}
|
|
20894
21664
|
async function isRipgrepAvailable() {
|
|
20895
21665
|
try {
|
|
20896
|
-
await
|
|
21666
|
+
await execFileAsync5("rg", ["--version"], { timeout: 2e3 });
|
|
20897
21667
|
return true;
|
|
20898
21668
|
} catch {
|
|
20899
21669
|
return false;
|
|
@@ -20913,7 +21683,7 @@ async function searchWithRipgrep(pattern, kind, options) {
|
|
|
20913
21683
|
args.push(pattern, options.rootDir);
|
|
20914
21684
|
let stdout;
|
|
20915
21685
|
try {
|
|
20916
|
-
const result = await
|
|
21686
|
+
const result = await execFileAsync5("rg", args, {
|
|
20917
21687
|
maxBuffer: 20 * 1024 * 1024,
|
|
20918
21688
|
timeout: 1e4
|
|
20919
21689
|
});
|
|
@@ -20956,7 +21726,7 @@ async function searchWithNodeFallback(pattern, kind, options) {
|
|
|
20956
21726
|
if (results.length >= maxMatches)
|
|
20957
21727
|
break;
|
|
20958
21728
|
try {
|
|
20959
|
-
const content = await
|
|
21729
|
+
const content = await readFile20(filePath, "utf-8");
|
|
20960
21730
|
const contentLines = content.split("\n");
|
|
20961
21731
|
for (let i = 0; i < contentLines.length; i++) {
|
|
20962
21732
|
if (results.length >= maxMatches)
|
|
@@ -21023,11 +21793,11 @@ function matchesGlob(filePath, glob2) {
|
|
|
21023
21793
|
return false;
|
|
21024
21794
|
}
|
|
21025
21795
|
}
|
|
21026
|
-
var
|
|
21796
|
+
var execFileAsync5, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS, DEFAULT_MAX_MATCHES, ALWAYS_SKIP, ALL_CODE_EXTS;
|
|
21027
21797
|
var init_lexicalSearch = __esm({
|
|
21028
21798
|
"packages/retrieval/dist/lexicalSearch.js"() {
|
|
21029
21799
|
"use strict";
|
|
21030
|
-
|
|
21800
|
+
execFileAsync5 = promisify5(execFile6);
|
|
21031
21801
|
DEFAULT_INCLUDE_GLOBS = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.py"];
|
|
21032
21802
|
DEFAULT_EXCLUDE_GLOBS = ["node_modules", "dist", ".git", "build", "coverage"];
|
|
21033
21803
|
DEFAULT_MAX_MATCHES = 50;
|
|
@@ -21299,7 +22069,7 @@ var init_graphExpand = __esm({
|
|
|
21299
22069
|
});
|
|
21300
22070
|
|
|
21301
22071
|
// packages/retrieval/dist/snippetPacker.js
|
|
21302
|
-
import { readFile as
|
|
22072
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
21303
22073
|
import { join as join41 } from "node:path";
|
|
21304
22074
|
async function packSnippets(requests, opts = {}) {
|
|
21305
22075
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
@@ -21329,7 +22099,7 @@ async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINE
|
|
|
21329
22099
|
const absPath = req.filePath.startsWith("/") ? req.filePath : join41(repoRoot, req.filePath);
|
|
21330
22100
|
let content;
|
|
21331
22101
|
try {
|
|
21332
|
-
content = await
|
|
22102
|
+
content = await readFile21(absPath, "utf-8");
|
|
21333
22103
|
} catch {
|
|
21334
22104
|
return null;
|
|
21335
22105
|
}
|
|
@@ -21864,9 +22634,9 @@ var init_verifierRunner = __esm({
|
|
|
21864
22634
|
async executeTests(patch, repoRoot) {
|
|
21865
22635
|
if (patch.testsToRun.length === 0)
|
|
21866
22636
|
return "(no tests specified)";
|
|
21867
|
-
const { execFile:
|
|
21868
|
-
const { promisify:
|
|
21869
|
-
const
|
|
22637
|
+
const { execFile: execFile7 } = await import("node:child_process");
|
|
22638
|
+
const { promisify: promisify7 } = await import("node:util");
|
|
22639
|
+
const execFileAsync6 = promisify7(execFile7);
|
|
21870
22640
|
const outputs = [];
|
|
21871
22641
|
const workDir = this.options.workingDir || repoRoot;
|
|
21872
22642
|
for (const cmd of patch.testsToRun.slice(0, 3)) {
|
|
@@ -21875,7 +22645,7 @@ var init_verifierRunner = __esm({
|
|
|
21875
22645
|
const [bin, ...args] = parts;
|
|
21876
22646
|
if (!bin)
|
|
21877
22647
|
continue;
|
|
21878
|
-
const { stdout, stderr } = await
|
|
22648
|
+
const { stdout, stderr } = await execFileAsync6(bin, args, {
|
|
21879
22649
|
cwd: workDir,
|
|
21880
22650
|
timeout: 6e4,
|
|
21881
22651
|
maxBuffer: 1024 * 1024
|
|
@@ -22555,6 +23325,7 @@ var init_agenticRunner = __esm({
|
|
|
22555
23325
|
init_dist();
|
|
22556
23326
|
init_personality();
|
|
22557
23327
|
init_promptLoader();
|
|
23328
|
+
init_dist2();
|
|
22558
23329
|
SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
|
|
22559
23330
|
SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
|
|
22560
23331
|
SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
|
|
@@ -22875,8 +23646,8 @@ ${this.options.dynamicContext}`,
|
|
|
22875
23646
|
async waitIfPaused() {
|
|
22876
23647
|
if (!this._paused)
|
|
22877
23648
|
return true;
|
|
22878
|
-
await new Promise((
|
|
22879
|
-
this._pauseResolve =
|
|
23649
|
+
await new Promise((resolve33) => {
|
|
23650
|
+
this._pauseResolve = resolve33;
|
|
22880
23651
|
});
|
|
22881
23652
|
return !this.aborted;
|
|
22882
23653
|
}
|
|
@@ -23909,14 +24680,14 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
23909
24680
|
waitForSudoPassword(timeoutMs = 12e4) {
|
|
23910
24681
|
if (this._sudoPassword)
|
|
23911
24682
|
return Promise.resolve(this._sudoPassword);
|
|
23912
|
-
return new Promise((
|
|
24683
|
+
return new Promise((resolve33) => {
|
|
23913
24684
|
const timer = setTimeout(() => {
|
|
23914
24685
|
this._sudoResolve = null;
|
|
23915
|
-
|
|
24686
|
+
resolve33(null);
|
|
23916
24687
|
}, timeoutMs);
|
|
23917
24688
|
this._sudoResolve = (pw) => {
|
|
23918
24689
|
clearTimeout(timer);
|
|
23919
|
-
|
|
24690
|
+
resolve33(pw);
|
|
23920
24691
|
};
|
|
23921
24692
|
});
|
|
23922
24693
|
}
|
|
@@ -24224,6 +24995,18 @@ ${tail}`;
|
|
|
24224
24995
|
const fileRegistryStr = this.formatFileRegistry();
|
|
24225
24996
|
if (fileRegistryStr)
|
|
24226
24997
|
enrichments.push(fileRegistryStr);
|
|
24998
|
+
try {
|
|
24999
|
+
const notesSummary = getWorkingNotesSummary();
|
|
25000
|
+
if (notesSummary)
|
|
25001
|
+
enrichments.push(notesSummary);
|
|
25002
|
+
const exploreNotes = getExploreNotes();
|
|
25003
|
+
if (exploreNotes.length > 0) {
|
|
25004
|
+
const exploreStr = `File exploration notes (${exploreNotes.length}):
|
|
25005
|
+
` + exploreNotes.map((n) => `- ${n.file} lines ${n.lineRange[0]}-${n.lineRange[1]}: ${n.finding}`).join("\n");
|
|
25006
|
+
enrichments.push(exploreStr);
|
|
25007
|
+
}
|
|
25008
|
+
} catch {
|
|
25009
|
+
}
|
|
24227
25010
|
if (tier === "large") {
|
|
24228
25011
|
const memexIndexStr = this.formatMemexIndex();
|
|
24229
25012
|
if (memexIndexStr)
|
|
@@ -25616,12 +26399,12 @@ var init_nexusBackend = __esm({
|
|
|
25616
26399
|
const deadline = Date.now() + (request.timeoutMs ?? 12e4);
|
|
25617
26400
|
try {
|
|
25618
26401
|
while (!done && Date.now() < deadline) {
|
|
25619
|
-
await new Promise((
|
|
26402
|
+
await new Promise((resolve33) => {
|
|
25620
26403
|
let resolved = false;
|
|
25621
26404
|
const finish = () => {
|
|
25622
26405
|
if (!resolved) {
|
|
25623
26406
|
resolved = true;
|
|
25624
|
-
|
|
26407
|
+
resolve33();
|
|
25625
26408
|
}
|
|
25626
26409
|
};
|
|
25627
26410
|
let watcher = null;
|
|
@@ -26561,7 +27344,7 @@ __export(listen_exports, {
|
|
|
26561
27344
|
import { spawn as spawn15, execSync as execSync22 } from "node:child_process";
|
|
26562
27345
|
import { existsSync as existsSync28, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, readdirSync as readdirSync6 } from "node:fs";
|
|
26563
27346
|
import { join as join43, dirname as dirname13 } from "node:path";
|
|
26564
|
-
import { homedir as
|
|
27347
|
+
import { homedir as homedir10 } from "node:os";
|
|
26565
27348
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
26566
27349
|
import { EventEmitter } from "node:events";
|
|
26567
27350
|
import { createInterface as createInterface2 } from "node:readline";
|
|
@@ -26673,7 +27456,7 @@ function findLiveWhisperScript() {
|
|
|
26673
27456
|
}
|
|
26674
27457
|
} catch {
|
|
26675
27458
|
}
|
|
26676
|
-
const nvmBase = join43(
|
|
27459
|
+
const nvmBase = join43(homedir10(), ".nvm", "versions", "node");
|
|
26677
27460
|
if (existsSync28(nvmBase)) {
|
|
26678
27461
|
try {
|
|
26679
27462
|
for (const ver of readdirSync6(nvmBase)) {
|
|
@@ -26703,9 +27486,9 @@ function ensureTranscribeCliBackground() {
|
|
|
26703
27486
|
}
|
|
26704
27487
|
try {
|
|
26705
27488
|
const { exec: exec4 } = await import("node:child_process");
|
|
26706
|
-
return new Promise((
|
|
27489
|
+
return new Promise((resolve33) => {
|
|
26707
27490
|
exec4("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
|
|
26708
|
-
|
|
27491
|
+
resolve33(!err);
|
|
26709
27492
|
});
|
|
26710
27493
|
});
|
|
26711
27494
|
} catch {
|
|
@@ -26764,7 +27547,7 @@ var init_listen = __esm({
|
|
|
26764
27547
|
return this._ready;
|
|
26765
27548
|
}
|
|
26766
27549
|
async start() {
|
|
26767
|
-
return new Promise((
|
|
27550
|
+
return new Promise((resolve33, reject) => {
|
|
26768
27551
|
const timeout = setTimeout(() => {
|
|
26769
27552
|
reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
|
|
26770
27553
|
}, 3e5);
|
|
@@ -26792,7 +27575,7 @@ var init_listen = __esm({
|
|
|
26792
27575
|
this._ready = true;
|
|
26793
27576
|
clearTimeout(timeout);
|
|
26794
27577
|
this.emit("ready");
|
|
26795
|
-
|
|
27578
|
+
resolve33();
|
|
26796
27579
|
break;
|
|
26797
27580
|
case "transcript":
|
|
26798
27581
|
this.emit("transcript", {
|
|
@@ -26927,7 +27710,7 @@ var init_listen = __esm({
|
|
|
26927
27710
|
}
|
|
26928
27711
|
} catch {
|
|
26929
27712
|
}
|
|
26930
|
-
const nvmBase = join43(
|
|
27713
|
+
const nvmBase = join43(homedir10(), ".nvm", "versions", "node");
|
|
26931
27714
|
if (existsSync28(nvmBase)) {
|
|
26932
27715
|
try {
|
|
26933
27716
|
const { readdirSync: readdirSync18 } = await import("node:fs");
|
|
@@ -26996,11 +27779,11 @@ var init_listen = __esm({
|
|
|
26996
27779
|
this.liveTranscriber.on("error", (err) => {
|
|
26997
27780
|
this.emit("error", err);
|
|
26998
27781
|
});
|
|
26999
|
-
await new Promise((
|
|
27782
|
+
await new Promise((resolve33, reject) => {
|
|
27000
27783
|
const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
|
|
27001
27784
|
this.liveTranscriber.on("ready", () => {
|
|
27002
27785
|
clearTimeout(timeout);
|
|
27003
|
-
|
|
27786
|
+
resolve33();
|
|
27004
27787
|
});
|
|
27005
27788
|
this.liveTranscriber.on("error", (err) => {
|
|
27006
27789
|
clearTimeout(timeout);
|
|
@@ -27162,11 +27945,11 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
27162
27945
|
sampleWidth: 2,
|
|
27163
27946
|
chunkDuration: 3
|
|
27164
27947
|
});
|
|
27165
|
-
await new Promise((
|
|
27948
|
+
await new Promise((resolve33, reject) => {
|
|
27166
27949
|
const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
|
|
27167
27950
|
transcriber.on("ready", () => {
|
|
27168
27951
|
clearTimeout(timeout);
|
|
27169
|
-
|
|
27952
|
+
resolve33();
|
|
27170
27953
|
});
|
|
27171
27954
|
transcriber.on("error", (err) => {
|
|
27172
27955
|
clearTimeout(timeout);
|
|
@@ -32137,8 +32920,8 @@ var init_voice_session = __esm({
|
|
|
32137
32920
|
this.server.keepAliveTimeout = 0;
|
|
32138
32921
|
this.wss = new import_websocket_server.default({ server: this.server, path: "/ws" });
|
|
32139
32922
|
this.wss.on("connection", (ws, req) => this.handleWSConnection(ws, req));
|
|
32140
|
-
await new Promise((
|
|
32141
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
32923
|
+
await new Promise((resolve33, reject) => {
|
|
32924
|
+
this.server.listen(port, "127.0.0.1", () => resolve33());
|
|
32142
32925
|
this.server.on("error", reject);
|
|
32143
32926
|
});
|
|
32144
32927
|
try {
|
|
@@ -32356,7 +33139,7 @@ var init_voice_session = __esm({
|
|
|
32356
33139
|
}
|
|
32357
33140
|
// ── Cloudflared tunnel ────────────────────────────────────────────────
|
|
32358
33141
|
startCloudflared(port) {
|
|
32359
|
-
return new Promise((
|
|
33142
|
+
return new Promise((resolve33, reject) => {
|
|
32360
33143
|
const timeout = setTimeout(() => {
|
|
32361
33144
|
reject(new Error("Cloudflared tunnel start timeout (30s)"));
|
|
32362
33145
|
}, 3e4);
|
|
@@ -32374,7 +33157,7 @@ var init_voice_session = __esm({
|
|
|
32374
33157
|
if (urlMatch && !urlFound) {
|
|
32375
33158
|
urlFound = true;
|
|
32376
33159
|
clearTimeout(timeout);
|
|
32377
|
-
|
|
33160
|
+
resolve33(urlMatch[0]);
|
|
32378
33161
|
}
|
|
32379
33162
|
};
|
|
32380
33163
|
this.cloudflaredProcess.stdout?.on("data", handleOutput);
|
|
@@ -32414,13 +33197,13 @@ var init_voice_session = __esm({
|
|
|
32414
33197
|
}
|
|
32415
33198
|
// ── Helpers ───────────────────────────────────────────────────────────
|
|
32416
33199
|
findFreePort() {
|
|
32417
|
-
return new Promise((
|
|
33200
|
+
return new Promise((resolve33, reject) => {
|
|
32418
33201
|
const srv = createServer2();
|
|
32419
33202
|
srv.listen(0, "127.0.0.1", () => {
|
|
32420
33203
|
const addr = srv.address();
|
|
32421
33204
|
if (addr && typeof addr === "object") {
|
|
32422
33205
|
const port = addr.port;
|
|
32423
|
-
srv.close(() =>
|
|
33206
|
+
srv.close(() => resolve33(port));
|
|
32424
33207
|
} else {
|
|
32425
33208
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
32426
33209
|
}
|
|
@@ -32543,8 +33326,8 @@ async function collectSystemMetricsAsync() {
|
|
|
32543
33326
|
vramUtilization: 0
|
|
32544
33327
|
};
|
|
32545
33328
|
try {
|
|
32546
|
-
const smi = await new Promise((
|
|
32547
|
-
exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
33329
|
+
const smi = await new Promise((resolve33, reject) => {
|
|
33330
|
+
exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
|
|
32548
33331
|
});
|
|
32549
33332
|
const line = smi.trim().split("\n")[0];
|
|
32550
33333
|
if (line) {
|
|
@@ -32692,8 +33475,8 @@ var init_expose = __esm({
|
|
|
32692
33475
|
throw new Error("Gateway already running");
|
|
32693
33476
|
const port = await this.findFreePort();
|
|
32694
33477
|
this.server = this.createProxyServer(port);
|
|
32695
|
-
await new Promise((
|
|
32696
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
33478
|
+
await new Promise((resolve33, reject) => {
|
|
33479
|
+
this.server.listen(port, "127.0.0.1", () => resolve33());
|
|
32697
33480
|
this.server.on("error", reject);
|
|
32698
33481
|
});
|
|
32699
33482
|
let lastStartErr;
|
|
@@ -32755,8 +33538,8 @@ var init_expose = __esm({
|
|
|
32755
33538
|
this._cloudflaredPid = state.pid;
|
|
32756
33539
|
this._proxyPort = state.proxyPort;
|
|
32757
33540
|
this.server = this.createProxyServer(state.proxyPort);
|
|
32758
|
-
await new Promise((
|
|
32759
|
-
this.server.listen(state.proxyPort, "127.0.0.1", () =>
|
|
33541
|
+
await new Promise((resolve33, reject) => {
|
|
33542
|
+
this.server.listen(state.proxyPort, "127.0.0.1", () => resolve33());
|
|
32760
33543
|
this.server.on("error", reject);
|
|
32761
33544
|
});
|
|
32762
33545
|
this._stats.status = "active";
|
|
@@ -32781,8 +33564,8 @@ var init_expose = __esm({
|
|
|
32781
33564
|
}
|
|
32782
33565
|
this._cloudflaredPid = null;
|
|
32783
33566
|
if (this.server) {
|
|
32784
|
-
await new Promise((
|
|
32785
|
-
this.server.close(() =>
|
|
33567
|
+
await new Promise((resolve33) => {
|
|
33568
|
+
this.server.close(() => resolve33());
|
|
32786
33569
|
});
|
|
32787
33570
|
this.server = null;
|
|
32788
33571
|
}
|
|
@@ -33114,7 +33897,7 @@ var init_expose = __esm({
|
|
|
33114
33897
|
_proxyPort = 0;
|
|
33115
33898
|
startCloudflared(port) {
|
|
33116
33899
|
this._proxyPort = port;
|
|
33117
|
-
return new Promise((
|
|
33900
|
+
return new Promise((resolve33, reject) => {
|
|
33118
33901
|
const timeout = setTimeout(() => {
|
|
33119
33902
|
reject(new Error("Cloudflared tunnel start timeout (30s)"));
|
|
33120
33903
|
}, 3e4);
|
|
@@ -33143,7 +33926,7 @@ var init_expose = __esm({
|
|
|
33143
33926
|
this.cloudflaredProcess?.unref();
|
|
33144
33927
|
this.cloudflaredProcess?.stdout?.destroy();
|
|
33145
33928
|
this.cloudflaredProcess?.stderr?.destroy();
|
|
33146
|
-
|
|
33929
|
+
resolve33(urlMatch[0]);
|
|
33147
33930
|
}
|
|
33148
33931
|
};
|
|
33149
33932
|
this.cloudflaredProcess.stdout?.on("data", handleOutput);
|
|
@@ -33232,13 +34015,13 @@ ${this.formatConnectionInfo()}`);
|
|
|
33232
34015
|
}
|
|
33233
34016
|
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
33234
34017
|
findFreePort() {
|
|
33235
|
-
return new Promise((
|
|
34018
|
+
return new Promise((resolve33, reject) => {
|
|
33236
34019
|
const srv = createServer3();
|
|
33237
34020
|
srv.listen(0, "127.0.0.1", () => {
|
|
33238
34021
|
const addr = srv.address();
|
|
33239
34022
|
if (addr && typeof addr === "object") {
|
|
33240
34023
|
const port = addr.port;
|
|
33241
|
-
srv.close(() =>
|
|
34024
|
+
srv.close(() => resolve33(port));
|
|
33242
34025
|
} else {
|
|
33243
34026
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
33244
34027
|
}
|
|
@@ -34185,8 +34968,8 @@ var init_peer_mesh = __esm({
|
|
|
34185
34968
|
this.wss.on("connection", (ws, req) => {
|
|
34186
34969
|
this.handleInboundConnection(ws, req.url ?? "");
|
|
34187
34970
|
});
|
|
34188
|
-
await new Promise((
|
|
34189
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
34971
|
+
await new Promise((resolve33, reject) => {
|
|
34972
|
+
this.server.listen(port, "127.0.0.1", () => resolve33());
|
|
34190
34973
|
this.server.on("error", reject);
|
|
34191
34974
|
});
|
|
34192
34975
|
this.pingTimer = setInterval(() => this.pingAll(), PING_INTERVAL_MS);
|
|
@@ -34225,7 +35008,7 @@ var init_peer_mesh = __esm({
|
|
|
34225
35008
|
this.wss = null;
|
|
34226
35009
|
}
|
|
34227
35010
|
if (this.server) {
|
|
34228
|
-
await new Promise((
|
|
35011
|
+
await new Promise((resolve33) => this.server.close(() => resolve33()));
|
|
34229
35012
|
this.server = null;
|
|
34230
35013
|
}
|
|
34231
35014
|
this.emit("stopped");
|
|
@@ -34243,7 +35026,7 @@ var init_peer_mesh = __esm({
|
|
|
34243
35026
|
if (!wsUrl.includes("/p2p"))
|
|
34244
35027
|
wsUrl += "/p2p";
|
|
34245
35028
|
wsUrl += `?key=${encodeURIComponent(this._authKey)}`;
|
|
34246
|
-
return new Promise((
|
|
35029
|
+
return new Promise((resolve33, reject) => {
|
|
34247
35030
|
const ws = new import_websocket.default(wsUrl, { handshakeTimeout: 1e4 });
|
|
34248
35031
|
let resolved = false;
|
|
34249
35032
|
const timeout = setTimeout(() => {
|
|
@@ -34283,7 +35066,7 @@ var init_peer_mesh = __esm({
|
|
|
34283
35066
|
this.connections.set(peer.peerId, ws);
|
|
34284
35067
|
this.setupPeerHandlers(ws, peer.peerId);
|
|
34285
35068
|
this.emit("peer_connected", peer);
|
|
34286
|
-
|
|
35069
|
+
resolve33(peer);
|
|
34287
35070
|
} else {
|
|
34288
35071
|
this.handleMessage(msg, ws);
|
|
34289
35072
|
}
|
|
@@ -34338,12 +35121,12 @@ var init_peer_mesh = __esm({
|
|
|
34338
35121
|
throw new Error(`Peer ${peerId} not connected`);
|
|
34339
35122
|
}
|
|
34340
35123
|
const msgId = randomBytes11(8).toString("hex");
|
|
34341
|
-
return new Promise((
|
|
35124
|
+
return new Promise((resolve33, reject) => {
|
|
34342
35125
|
const timeout = setTimeout(() => {
|
|
34343
35126
|
this.pendingRequests.delete(msgId);
|
|
34344
35127
|
reject(new Error(`Inference timeout (${timeoutMs}ms)`));
|
|
34345
35128
|
}, timeoutMs);
|
|
34346
|
-
this.pendingRequests.set(msgId, { resolve:
|
|
35129
|
+
this.pendingRequests.set(msgId, { resolve: resolve33, reject, timeout, chunks: [] });
|
|
34347
35130
|
this.sendMsg(ws, "infer_request", request, msgId);
|
|
34348
35131
|
});
|
|
34349
35132
|
}
|
|
@@ -34565,13 +35348,13 @@ var init_peer_mesh = __esm({
|
|
|
34565
35348
|
ws.send(JSON.stringify(msg));
|
|
34566
35349
|
}
|
|
34567
35350
|
findFreePort() {
|
|
34568
|
-
return new Promise((
|
|
35351
|
+
return new Promise((resolve33, reject) => {
|
|
34569
35352
|
const srv = createServer4();
|
|
34570
35353
|
srv.listen(0, "127.0.0.1", () => {
|
|
34571
35354
|
const addr = srv.address();
|
|
34572
35355
|
if (addr && typeof addr === "object") {
|
|
34573
35356
|
const port = addr.port;
|
|
34574
|
-
srv.close(() =>
|
|
35357
|
+
srv.close(() => resolve33(port));
|
|
34575
35358
|
} else {
|
|
34576
35359
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
34577
35360
|
}
|
|
@@ -35817,7 +36600,7 @@ __export(oa_directory_exports, {
|
|
|
35817
36600
|
});
|
|
35818
36601
|
import { existsSync as existsSync32, mkdirSync as mkdirSync11, readFileSync as readFileSync23, writeFileSync as writeFileSync12, readdirSync as readdirSync8, statSync as statSync11, unlinkSync as unlinkSync6 } from "node:fs";
|
|
35819
36602
|
import { join as join48, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
35820
|
-
import { homedir as
|
|
36603
|
+
import { homedir as homedir11 } from "node:os";
|
|
35821
36604
|
function initOaDirectory(repoRoot) {
|
|
35822
36605
|
const oaPath = join48(repoRoot, OA_DIR);
|
|
35823
36606
|
for (const sub of SUBDIRS) {
|
|
@@ -35857,7 +36640,7 @@ function saveProjectSettings(repoRoot, settings) {
|
|
|
35857
36640
|
writeFileSync12(join48(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
35858
36641
|
}
|
|
35859
36642
|
function loadGlobalSettings() {
|
|
35860
|
-
const settingsPath = join48(
|
|
36643
|
+
const settingsPath = join48(homedir11(), ".open-agents", "settings.json");
|
|
35861
36644
|
try {
|
|
35862
36645
|
if (existsSync32(settingsPath)) {
|
|
35863
36646
|
return JSON.parse(readFileSync23(settingsPath, "utf-8"));
|
|
@@ -35867,7 +36650,7 @@ function loadGlobalSettings() {
|
|
|
35867
36650
|
return {};
|
|
35868
36651
|
}
|
|
35869
36652
|
function saveGlobalSettings(settings) {
|
|
35870
|
-
const dir = join48(
|
|
36653
|
+
const dir = join48(homedir11(), ".open-agents");
|
|
35871
36654
|
mkdirSync11(dir, { recursive: true });
|
|
35872
36655
|
const existing = loadGlobalSettings();
|
|
35873
36656
|
const merged = { ...existing, ...settings };
|
|
@@ -36247,13 +37030,13 @@ function recordUsage(kind, value, opts) {
|
|
|
36247
37030
|
}
|
|
36248
37031
|
saveUsageFile(filePath, data);
|
|
36249
37032
|
};
|
|
36250
|
-
update(join48(
|
|
37033
|
+
update(join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
|
|
36251
37034
|
if (opts?.repoRoot) {
|
|
36252
37035
|
update(join48(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
36253
37036
|
}
|
|
36254
37037
|
}
|
|
36255
37038
|
function loadUsageHistory(kind, repoRoot) {
|
|
36256
|
-
const globalPath = join48(
|
|
37039
|
+
const globalPath = join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE);
|
|
36257
37040
|
const globalData = loadUsageFile(globalPath);
|
|
36258
37041
|
const localData = repoRoot ? loadUsageFile(join48(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
|
|
36259
37042
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -36286,7 +37069,7 @@ function deleteUsageRecord(kind, value, repoRoot) {
|
|
|
36286
37069
|
saveUsageFile(filePath, data);
|
|
36287
37070
|
}
|
|
36288
37071
|
};
|
|
36289
|
-
remove(join48(
|
|
37072
|
+
remove(join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
|
|
36290
37073
|
if (repoRoot) {
|
|
36291
37074
|
remove(join48(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
36292
37075
|
}
|
|
@@ -36337,10 +37120,10 @@ var init_oa_directory = __esm({
|
|
|
36337
37120
|
// packages/cli/dist/tui/setup.js
|
|
36338
37121
|
import * as readline from "node:readline";
|
|
36339
37122
|
import { execSync as execSync24, spawn as spawn18, exec as exec2 } from "node:child_process";
|
|
36340
|
-
import { promisify as
|
|
37123
|
+
import { promisify as promisify6 } from "node:util";
|
|
36341
37124
|
import { existsSync as existsSync33, writeFileSync as writeFileSync13, readFileSync as readFileSync24, appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
|
|
36342
37125
|
import { join as join49 } from "node:path";
|
|
36343
|
-
import { homedir as
|
|
37126
|
+
import { homedir as homedir12, platform } from "node:os";
|
|
36344
37127
|
function detectSystemSpecs() {
|
|
36345
37128
|
let totalRamGB = 0;
|
|
36346
37129
|
let availableRamGB = 0;
|
|
@@ -36477,12 +37260,12 @@ function modelSupportsToolCalling(modelName) {
|
|
|
36477
37260
|
return false;
|
|
36478
37261
|
}
|
|
36479
37262
|
function ask(rl, question) {
|
|
36480
|
-
return new Promise((
|
|
36481
|
-
rl.question(question, (answer) =>
|
|
37263
|
+
return new Promise((resolve33) => {
|
|
37264
|
+
rl.question(question, (answer) => resolve33(answer.trim()));
|
|
36482
37265
|
});
|
|
36483
37266
|
}
|
|
36484
37267
|
function askSecret(rl, question) {
|
|
36485
|
-
return new Promise((
|
|
37268
|
+
return new Promise((resolve33) => {
|
|
36486
37269
|
process.stdout.write(question);
|
|
36487
37270
|
let secret = "";
|
|
36488
37271
|
const stdin = process.stdin;
|
|
@@ -36500,7 +37283,7 @@ function askSecret(rl, question) {
|
|
|
36500
37283
|
stdin.setRawMode(hadRawMode ?? false);
|
|
36501
37284
|
}
|
|
36502
37285
|
process.stdout.write("\n");
|
|
36503
|
-
|
|
37286
|
+
resolve33(secret.trim());
|
|
36504
37287
|
return;
|
|
36505
37288
|
} else if (c3 === "") {
|
|
36506
37289
|
stdin.removeListener("data", onData);
|
|
@@ -36508,7 +37291,7 @@ function askSecret(rl, question) {
|
|
|
36508
37291
|
stdin.setRawMode(hadRawMode ?? false);
|
|
36509
37292
|
}
|
|
36510
37293
|
process.stdout.write("\n");
|
|
36511
|
-
|
|
37294
|
+
resolve33("");
|
|
36512
37295
|
return;
|
|
36513
37296
|
} else if (c3 === "\x7F" || c3 === "\b") {
|
|
36514
37297
|
if (secret.length > 0) {
|
|
@@ -36743,7 +37526,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
36743
37526
|
return false;
|
|
36744
37527
|
}
|
|
36745
37528
|
for (let i = 0; i < 5; i++) {
|
|
36746
|
-
await new Promise((
|
|
37529
|
+
await new Promise((resolve33) => setTimeout(resolve33, 2e3));
|
|
36747
37530
|
try {
|
|
36748
37531
|
const resp = await fetch(`${backendUrl}/api/tags`, {
|
|
36749
37532
|
signal: AbortSignal.timeout(3e3)
|
|
@@ -37204,7 +37987,7 @@ async function doSetup(config, rl) {
|
|
|
37204
37987
|
try {
|
|
37205
37988
|
const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
37206
37989
|
child.unref();
|
|
37207
|
-
await new Promise((
|
|
37990
|
+
await new Promise((resolve33) => setTimeout(resolve33, 3e3));
|
|
37208
37991
|
try {
|
|
37209
37992
|
models = await fetchOllamaModels(config.backendUrl);
|
|
37210
37993
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -37232,7 +38015,7 @@ async function doSetup(config, rl) {
|
|
|
37232
38015
|
try {
|
|
37233
38016
|
const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
37234
38017
|
child.unref();
|
|
37235
|
-
await new Promise((
|
|
38018
|
+
await new Promise((resolve33) => setTimeout(resolve33, 3e3));
|
|
37236
38019
|
try {
|
|
37237
38020
|
models = await fetchOllamaModels(config.backendUrl);
|
|
37238
38021
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -37380,7 +38163,7 @@ async function doSetup(config, rl) {
|
|
|
37380
38163
|
`PARAMETER num_predict ${numPredict}`,
|
|
37381
38164
|
`PARAMETER stop "<|endoftext|>"`
|
|
37382
38165
|
].join("\n");
|
|
37383
|
-
const modelDir2 = join49(
|
|
38166
|
+
const modelDir2 = join49(homedir12(), ".open-agents", "models");
|
|
37384
38167
|
mkdirSync12(modelDir2, { recursive: true });
|
|
37385
38168
|
const modelfilePath = join49(modelDir2, `Modelfile.${customName}`);
|
|
37386
38169
|
writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
|
|
@@ -37428,7 +38211,7 @@ async function isModelAvailable(config) {
|
|
|
37428
38211
|
}
|
|
37429
38212
|
function isFirstRun() {
|
|
37430
38213
|
try {
|
|
37431
|
-
return !existsSync33(join49(
|
|
38214
|
+
return !existsSync33(join49(homedir12(), ".open-agents", "config.json"));
|
|
37432
38215
|
} catch {
|
|
37433
38216
|
return true;
|
|
37434
38217
|
}
|
|
@@ -37465,7 +38248,7 @@ function detectPkgManager() {
|
|
|
37465
38248
|
return null;
|
|
37466
38249
|
}
|
|
37467
38250
|
function getVenvDir() {
|
|
37468
|
-
return join49(
|
|
38251
|
+
return join49(homedir12(), ".open-agents", "venv");
|
|
37469
38252
|
}
|
|
37470
38253
|
function hasVenvModule() {
|
|
37471
38254
|
try {
|
|
@@ -37490,7 +38273,7 @@ function ensureVenv(log) {
|
|
|
37490
38273
|
return null;
|
|
37491
38274
|
}
|
|
37492
38275
|
try {
|
|
37493
|
-
mkdirSync12(join49(
|
|
38276
|
+
mkdirSync12(join49(homedir12(), ".open-agents"), { recursive: true });
|
|
37494
38277
|
execSync24(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
37495
38278
|
execSync24(`"${join49(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
37496
38279
|
stdio: "pipe",
|
|
@@ -37756,9 +38539,9 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
37756
38539
|
const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
|
|
37757
38540
|
const cfArch = archMap[arch] ?? "amd64";
|
|
37758
38541
|
try {
|
|
37759
|
-
execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${
|
|
37760
|
-
if (!process.env.PATH?.includes(`${
|
|
37761
|
-
process.env.PATH = `${
|
|
38542
|
+
execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir12()}/.local/bin" && mv /tmp/cloudflared "${homedir12()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
|
|
38543
|
+
if (!process.env.PATH?.includes(`${homedir12()}/.local/bin`)) {
|
|
38544
|
+
process.env.PATH = `${homedir12()}/.local/bin:${process.env.PATH}`;
|
|
37762
38545
|
}
|
|
37763
38546
|
if (hasCmd("cloudflared")) {
|
|
37764
38547
|
log("cloudflared installed.");
|
|
@@ -37853,7 +38636,7 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
|
|
|
37853
38636
|
`PARAMETER num_predict ${numPredict}`,
|
|
37854
38637
|
`PARAMETER stop "<|endoftext|>"`
|
|
37855
38638
|
].join("\n");
|
|
37856
|
-
const modelDir2 = join49(
|
|
38639
|
+
const modelDir2 = join49(homedir12(), ".open-agents", "models");
|
|
37857
38640
|
mkdirSync12(modelDir2, { recursive: true });
|
|
37858
38641
|
const modelfilePath = join49(modelDir2, `Modelfile.${customName}`);
|
|
37859
38642
|
writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
|
|
@@ -37930,7 +38713,7 @@ async function ensureNeovim() {
|
|
|
37930
38713
|
const platform5 = process.platform;
|
|
37931
38714
|
const arch = process.arch;
|
|
37932
38715
|
if (platform5 === "linux") {
|
|
37933
|
-
const binDir = join49(
|
|
38716
|
+
const binDir = join49(homedir12(), ".local", "bin");
|
|
37934
38717
|
const nvimDest = join49(binDir, "nvim");
|
|
37935
38718
|
try {
|
|
37936
38719
|
mkdirSync12(binDir, { recursive: true });
|
|
@@ -38002,7 +38785,7 @@ async function ensureNeovim() {
|
|
|
38002
38785
|
}
|
|
38003
38786
|
function ensurePathInShellRc(binDir) {
|
|
38004
38787
|
const shell = process.env.SHELL ?? "";
|
|
38005
|
-
const rcFile = shell.includes("zsh") ? join49(
|
|
38788
|
+
const rcFile = shell.includes("zsh") ? join49(homedir12(), ".zshrc") : join49(homedir12(), ".bashrc");
|
|
38006
38789
|
try {
|
|
38007
38790
|
const rcContent = existsSync33(rcFile) ? readFileSync24(rcFile, "utf8") : "";
|
|
38008
38791
|
if (rcContent.includes(binDir))
|
|
@@ -38023,7 +38806,7 @@ var init_setup = __esm({
|
|
|
38023
38806
|
init_render();
|
|
38024
38807
|
init_config();
|
|
38025
38808
|
init_dist();
|
|
38026
|
-
execAsync =
|
|
38809
|
+
execAsync = promisify6(exec2);
|
|
38027
38810
|
QWEN_VARIANTS = [
|
|
38028
38811
|
{ tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
|
|
38029
38812
|
{ tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
|
|
@@ -38221,7 +39004,7 @@ function tuiSelect(opts) {
|
|
|
38221
39004
|
const maxVisible = opts.maxVisible ?? Math.max(3, contentArea - selectChrome);
|
|
38222
39005
|
let scrollOffset = 0;
|
|
38223
39006
|
let lastRenderedLines = 0;
|
|
38224
|
-
return new Promise((
|
|
39007
|
+
return new Promise((resolve33) => {
|
|
38225
39008
|
const stdin = process.stdin;
|
|
38226
39009
|
const hadRawMode = stdin.isRaw;
|
|
38227
39010
|
const savedRlListeners = [];
|
|
@@ -38396,7 +39179,7 @@ function tuiSelect(opts) {
|
|
|
38396
39179
|
if (!isSkippable(itemIdx) && matchSet.has(itemIdx)) {
|
|
38397
39180
|
cursor = itemIdx;
|
|
38398
39181
|
cleanup();
|
|
38399
|
-
|
|
39182
|
+
resolve33({ confirmed: true, key: items[cursor].key, index: cursor });
|
|
38400
39183
|
return;
|
|
38401
39184
|
} else if (!isSkippable(itemIdx)) {
|
|
38402
39185
|
cursor = itemIdx;
|
|
@@ -38472,7 +39255,7 @@ function tuiSelect(opts) {
|
|
|
38472
39255
|
items.splice(deletedIdx, 1);
|
|
38473
39256
|
if (items.length === 0) {
|
|
38474
39257
|
cleanup();
|
|
38475
|
-
|
|
39258
|
+
resolve33({ confirmed: false, key: null, index: -1 });
|
|
38476
39259
|
return;
|
|
38477
39260
|
}
|
|
38478
39261
|
updateFilter();
|
|
@@ -38561,7 +39344,7 @@ function tuiSelect(opts) {
|
|
|
38561
39344
|
} else if (seq === "\r" || seq === "\n") {
|
|
38562
39345
|
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
38563
39346
|
cleanup();
|
|
38564
|
-
|
|
39347
|
+
resolve33({ confirmed: true, key: items[cursor].key, index: cursor });
|
|
38565
39348
|
}
|
|
38566
39349
|
} else if (seq === "\x1B" || seq === "\x1B\x1B") {
|
|
38567
39350
|
if (filter) {
|
|
@@ -38574,14 +39357,14 @@ function tuiSelect(opts) {
|
|
|
38574
39357
|
render();
|
|
38575
39358
|
} else if (hasBreadcrumbs) {
|
|
38576
39359
|
cleanup();
|
|
38577
|
-
|
|
39360
|
+
resolve33({ confirmed: false, key: "__back__", index: cursor });
|
|
38578
39361
|
} else {
|
|
38579
39362
|
cleanup();
|
|
38580
|
-
|
|
39363
|
+
resolve33({ confirmed: false, key: null, index: cursor });
|
|
38581
39364
|
}
|
|
38582
39365
|
} else if (seq === "") {
|
|
38583
39366
|
cleanup();
|
|
38584
|
-
|
|
39367
|
+
resolve33({ confirmed: false, key: null, index: cursor });
|
|
38585
39368
|
} else if (seq === "\x7F" || seq === "\b") {
|
|
38586
39369
|
if (filter.length > 0) {
|
|
38587
39370
|
filter = filter.slice(0, -1);
|
|
@@ -38595,7 +39378,7 @@ function tuiSelect(opts) {
|
|
|
38595
39378
|
render();
|
|
38596
39379
|
} else if (hasBreadcrumbs) {
|
|
38597
39380
|
cleanup();
|
|
38598
|
-
|
|
39381
|
+
resolve33({ confirmed: false, key: "__back__", index: cursor });
|
|
38599
39382
|
}
|
|
38600
39383
|
} else if (seq.length === 1 && seq.charCodeAt(0) >= 32 && seq.charCodeAt(0) < 127) {
|
|
38601
39384
|
if (opts.onCustomKey && !isSkippable(cursor) && matchSet.has(cursor)) {
|
|
@@ -38603,7 +39386,7 @@ function tuiSelect(opts) {
|
|
|
38603
39386
|
done: () => render(),
|
|
38604
39387
|
resolve: (result) => {
|
|
38605
39388
|
cleanup();
|
|
38606
|
-
|
|
39389
|
+
resolve33(result);
|
|
38607
39390
|
},
|
|
38608
39391
|
getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
|
|
38609
39392
|
render: () => render(),
|
|
@@ -38720,7 +39503,7 @@ var init_tui_select = __esm({
|
|
|
38720
39503
|
|
|
38721
39504
|
// packages/cli/dist/tui/drop-panel.js
|
|
38722
39505
|
import { existsSync as existsSync34 } from "node:fs";
|
|
38723
|
-
import { extname as extname9, resolve as
|
|
39506
|
+
import { extname as extname9, resolve as resolve28 } from "node:path";
|
|
38724
39507
|
function ansi4(code, text) {
|
|
38725
39508
|
return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
38726
39509
|
}
|
|
@@ -38833,7 +39616,7 @@ function showDropPanel(opts) {
|
|
|
38833
39616
|
if (filePath.startsWith("file://")) {
|
|
38834
39617
|
filePath = decodeURIComponent(filePath.slice(7));
|
|
38835
39618
|
}
|
|
38836
|
-
filePath =
|
|
39619
|
+
filePath = resolve28(filePath);
|
|
38837
39620
|
if (!existsSync34(filePath)) {
|
|
38838
39621
|
errorMsg = `File not found: ${filePath}`;
|
|
38839
39622
|
render();
|
|
@@ -39145,12 +39928,12 @@ function stopNeovimMode() {
|
|
|
39145
39928
|
} catch {
|
|
39146
39929
|
}
|
|
39147
39930
|
const s = _state;
|
|
39148
|
-
return new Promise((
|
|
39931
|
+
return new Promise((resolve33) => {
|
|
39149
39932
|
setTimeout(() => {
|
|
39150
39933
|
if (s && !s.cleanedUp) {
|
|
39151
39934
|
doCleanup(s);
|
|
39152
39935
|
}
|
|
39153
|
-
|
|
39936
|
+
resolve33();
|
|
39154
39937
|
}, 300);
|
|
39155
39938
|
});
|
|
39156
39939
|
}
|
|
@@ -39386,7 +40169,7 @@ __export(voice_exports, {
|
|
|
39386
40169
|
});
|
|
39387
40170
|
import { existsSync as existsSync36, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync25, unlinkSync as unlinkSync8, readdirSync as readdirSync9, renameSync, statSync as statSync12 } from "node:fs";
|
|
39388
40171
|
import { join as join51, dirname as dirname17 } from "node:path";
|
|
39389
|
-
import { homedir as
|
|
40172
|
+
import { homedir as homedir13, tmpdir as tmpdir9, platform as platform2 } from "node:os";
|
|
39390
40173
|
import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
|
|
39391
40174
|
import { createRequire } from "node:module";
|
|
39392
40175
|
function sanitizeForTTS(text) {
|
|
@@ -39410,7 +40193,7 @@ function listVoiceModels() {
|
|
|
39410
40193
|
}));
|
|
39411
40194
|
}
|
|
39412
40195
|
function voiceDir() {
|
|
39413
|
-
return join51(
|
|
40196
|
+
return join51(homedir13(), ".open-agents", "voice");
|
|
39414
40197
|
}
|
|
39415
40198
|
function modelsDir() {
|
|
39416
40199
|
return join51(voiceDir(), "models");
|
|
@@ -40406,7 +41189,7 @@ var init_voice = __esm({
|
|
|
40406
41189
|
}
|
|
40407
41190
|
p = p.replace(/\\ /g, " ");
|
|
40408
41191
|
if (p.startsWith("~/") || p === "~") {
|
|
40409
|
-
p = join51(
|
|
41192
|
+
p = join51(homedir13(), p.slice(1));
|
|
40410
41193
|
}
|
|
40411
41194
|
if (!existsSync36(p)) {
|
|
40412
41195
|
return `File not found: ${p}
|
|
@@ -40821,7 +41604,7 @@ var init_voice = __esm({
|
|
|
40821
41604
|
this.speaking = false;
|
|
40822
41605
|
}
|
|
40823
41606
|
sleep(ms) {
|
|
40824
|
-
return new Promise((
|
|
41607
|
+
return new Promise((resolve33) => setTimeout(resolve33, ms));
|
|
40825
41608
|
}
|
|
40826
41609
|
// -------------------------------------------------------------------------
|
|
40827
41610
|
// Synthesis pipeline
|
|
@@ -41087,7 +41870,7 @@ var init_voice = __esm({
|
|
|
41087
41870
|
const cmd = this.getPlayCommand(path);
|
|
41088
41871
|
if (!cmd)
|
|
41089
41872
|
return;
|
|
41090
|
-
return new Promise((
|
|
41873
|
+
return new Promise((resolve33) => {
|
|
41091
41874
|
const child = nodeSpawn(cmd[0], cmd.slice(1), {
|
|
41092
41875
|
stdio: "ignore",
|
|
41093
41876
|
detached: false
|
|
@@ -41096,12 +41879,12 @@ var init_voice = __esm({
|
|
|
41096
41879
|
child.on("close", () => {
|
|
41097
41880
|
if (this.currentPlayback === child)
|
|
41098
41881
|
this.currentPlayback = null;
|
|
41099
|
-
|
|
41882
|
+
resolve33();
|
|
41100
41883
|
});
|
|
41101
41884
|
child.on("error", () => {
|
|
41102
41885
|
if (this.currentPlayback === child)
|
|
41103
41886
|
this.currentPlayback = null;
|
|
41104
|
-
|
|
41887
|
+
resolve33();
|
|
41105
41888
|
});
|
|
41106
41889
|
setTimeout(() => {
|
|
41107
41890
|
if (this.currentPlayback === child) {
|
|
@@ -41111,7 +41894,7 @@ var init_voice = __esm({
|
|
|
41111
41894
|
}
|
|
41112
41895
|
this.currentPlayback = null;
|
|
41113
41896
|
}
|
|
41114
|
-
|
|
41897
|
+
resolve33();
|
|
41115
41898
|
}, 15e3);
|
|
41116
41899
|
});
|
|
41117
41900
|
}
|
|
@@ -41186,7 +41969,7 @@ var init_voice = __esm({
|
|
|
41186
41969
|
/** Non-blocking shell execution — async alternative to execSync.
|
|
41187
41970
|
* Returns stdout string on exit 0, rejects otherwise. */
|
|
41188
41971
|
asyncShell(command, timeoutMs = 3e4) {
|
|
41189
|
-
return new Promise((
|
|
41972
|
+
return new Promise((resolve33, reject) => {
|
|
41190
41973
|
const proc = nodeSpawn("sh", ["-c", command], {
|
|
41191
41974
|
stdio: ["ignore", "pipe", "pipe"],
|
|
41192
41975
|
cwd: tmpdir9()
|
|
@@ -41207,7 +41990,7 @@ var init_voice = __esm({
|
|
|
41207
41990
|
proc.on("close", (code) => {
|
|
41208
41991
|
clearTimeout(timer);
|
|
41209
41992
|
if (code === 0)
|
|
41210
|
-
|
|
41993
|
+
resolve33(stdout.trim());
|
|
41211
41994
|
else
|
|
41212
41995
|
reject(new Error(stderr.slice(0, 300) || `Exit code ${code}`));
|
|
41213
41996
|
});
|
|
@@ -41692,7 +42475,7 @@ if __name__ == '__main__':
|
|
|
41692
42475
|
const venvPy = luxttsVenvPy();
|
|
41693
42476
|
if (!existsSync36(venvPy))
|
|
41694
42477
|
return false;
|
|
41695
|
-
return new Promise((
|
|
42478
|
+
return new Promise((resolve33) => {
|
|
41696
42479
|
const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
41697
42480
|
const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
|
|
41698
42481
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -41711,7 +42494,7 @@ if __name__ == '__main__':
|
|
|
41711
42494
|
try {
|
|
41712
42495
|
const msg = JSON.parse(line);
|
|
41713
42496
|
if (msg.type === "ready") {
|
|
41714
|
-
|
|
42497
|
+
resolve33(true);
|
|
41715
42498
|
} else if (msg.type === "result" || msg.type === "error") {
|
|
41716
42499
|
const pending = this._luxttsPending.get(msg.id);
|
|
41717
42500
|
if (pending) {
|
|
@@ -41735,25 +42518,25 @@ if __name__ == '__main__':
|
|
|
41735
42518
|
});
|
|
41736
42519
|
daemon.on("error", () => {
|
|
41737
42520
|
this._luxttsDaemon = null;
|
|
41738
|
-
|
|
42521
|
+
resolve33(false);
|
|
41739
42522
|
});
|
|
41740
42523
|
setTimeout(() => {
|
|
41741
42524
|
if (this._luxttsDaemon === daemon && !this._luxttsPending.has("__ready__")) {
|
|
41742
|
-
|
|
42525
|
+
resolve33(false);
|
|
41743
42526
|
}
|
|
41744
42527
|
}, 6e4);
|
|
41745
42528
|
});
|
|
41746
42529
|
}
|
|
41747
42530
|
/** Send a request to the LuxTTS daemon and await the response */
|
|
41748
42531
|
luxttsRequest(req) {
|
|
41749
|
-
return new Promise((
|
|
42532
|
+
return new Promise((resolve33, reject) => {
|
|
41750
42533
|
if (!this._luxttsDaemon || this._luxttsDaemon.killed) {
|
|
41751
42534
|
reject(new Error("LuxTTS daemon not running"));
|
|
41752
42535
|
return;
|
|
41753
42536
|
}
|
|
41754
42537
|
const id = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
41755
42538
|
req.id = id;
|
|
41756
|
-
this._luxttsPending.set(id, { resolve:
|
|
42539
|
+
this._luxttsPending.set(id, { resolve: resolve33, reject });
|
|
41757
42540
|
this._luxttsDaemon.stdin.write(JSON.stringify(req) + "\n");
|
|
41758
42541
|
setTimeout(() => {
|
|
41759
42542
|
if (this._luxttsPending.has(id)) {
|
|
@@ -44777,9 +45560,9 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
|
|
|
44777
45560
|
}
|
|
44778
45561
|
const { basename: basename16, join: pathJoin } = await import("node:path");
|
|
44779
45562
|
const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync22, existsSync: exists } = await import("node:fs");
|
|
44780
|
-
const { homedir:
|
|
45563
|
+
const { homedir: homedir18 } = await import("node:os");
|
|
44781
45564
|
const modelName = basename16(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
44782
|
-
const destDir = pathJoin(
|
|
45565
|
+
const destDir = pathJoin(homedir18(), ".open-agents", "voice", "models", modelName);
|
|
44783
45566
|
if (!exists(destDir))
|
|
44784
45567
|
mkdirSync22(destDir, { recursive: true });
|
|
44785
45568
|
copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
@@ -45680,11 +46463,11 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
45680
46463
|
const targetVersion = info?.latestVersion ?? currentVersion;
|
|
45681
46464
|
const installOverlay = startInstallOverlay(targetVersion);
|
|
45682
46465
|
let installError = "";
|
|
45683
|
-
const runInstall2 = (cmd) => new Promise((
|
|
46466
|
+
const runInstall2 = (cmd) => new Promise((resolve33) => {
|
|
45684
46467
|
const child = exec4(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
|
|
45685
46468
|
if (err)
|
|
45686
46469
|
installError = (stderr || err.message || "").trim();
|
|
45687
|
-
|
|
46470
|
+
resolve33(!err);
|
|
45688
46471
|
});
|
|
45689
46472
|
child.stdout?.on("data", (chunk) => {
|
|
45690
46473
|
const text = String(chunk);
|
|
@@ -45778,8 +46561,8 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
45778
46561
|
}
|
|
45779
46562
|
if (doRebuild) {
|
|
45780
46563
|
installOverlay.setStatus("Rebuilding native modules...");
|
|
45781
|
-
await new Promise((
|
|
45782
|
-
const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () =>
|
|
46564
|
+
await new Promise((resolve33) => {
|
|
46565
|
+
const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve33(true));
|
|
45783
46566
|
child.stdout?.resume();
|
|
45784
46567
|
child.stderr?.resume();
|
|
45785
46568
|
});
|
|
@@ -45810,8 +46593,8 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
45810
46593
|
const venvPip = pathJoin(venvDir, "bin", "pip");
|
|
45811
46594
|
if (fsExists(venvPip)) {
|
|
45812
46595
|
installOverlay.setStatus("Upgrading Python packages...");
|
|
45813
|
-
await new Promise((
|
|
45814
|
-
const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) =>
|
|
46596
|
+
await new Promise((resolve33) => {
|
|
46597
|
+
const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve33(!err));
|
|
45815
46598
|
child.stdout?.resume();
|
|
45816
46599
|
child.stderr?.resume();
|
|
45817
46600
|
});
|
|
@@ -46207,16 +46990,16 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
46207
46990
|
renderDashboard();
|
|
46208
46991
|
}, 1e3);
|
|
46209
46992
|
let stopGateway = false;
|
|
46210
|
-
await new Promise((
|
|
46993
|
+
await new Promise((resolve33) => {
|
|
46211
46994
|
const onData = (data) => {
|
|
46212
46995
|
const key = data.toString();
|
|
46213
46996
|
if (key === "q" || key === "Q" || key === "\x1B" || key === "") {
|
|
46214
|
-
|
|
46997
|
+
resolve33();
|
|
46215
46998
|
return;
|
|
46216
46999
|
}
|
|
46217
47000
|
if (key === "s" || key === "S") {
|
|
46218
47001
|
stopGateway = true;
|
|
46219
|
-
|
|
47002
|
+
resolve33();
|
|
46220
47003
|
return;
|
|
46221
47004
|
}
|
|
46222
47005
|
if (key === "c" || key === "C") {
|
|
@@ -46267,8 +47050,8 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
46267
47050
|
process.stdout.write("\x1B[?1002h\x1B[?1006h");
|
|
46268
47051
|
}
|
|
46269
47052
|
};
|
|
46270
|
-
const origResolve =
|
|
46271
|
-
|
|
47053
|
+
const origResolve = resolve33;
|
|
47054
|
+
resolve33 = (() => {
|
|
46272
47055
|
cleanup();
|
|
46273
47056
|
origResolve();
|
|
46274
47057
|
});
|
|
@@ -46326,7 +47109,7 @@ var init_commands = __esm({
|
|
|
46326
47109
|
import { existsSync as existsSync38, readFileSync as readFileSync27, readdirSync as readdirSync11 } from "node:fs";
|
|
46327
47110
|
import { join as join53, basename as basename10 } from "node:path";
|
|
46328
47111
|
import { execSync as execSync27 } from "node:child_process";
|
|
46329
|
-
import { homedir as
|
|
47112
|
+
import { homedir as homedir15, platform as platform3, release } from "node:os";
|
|
46330
47113
|
function getModelTier(modelName) {
|
|
46331
47114
|
const m = modelName.toLowerCase();
|
|
46332
47115
|
const sizeMatch = m.match(/\b(\d+)b\b/);
|
|
@@ -46413,7 +47196,7 @@ function loadMemoryContext(repoRoot) {
|
|
|
46413
47196
|
if (legacyEntries)
|
|
46414
47197
|
sections.push(legacyEntries);
|
|
46415
47198
|
}
|
|
46416
|
-
const globalMemDir = join53(
|
|
47199
|
+
const globalMemDir = join53(homedir15(), ".open-agents", "memory");
|
|
46417
47200
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
46418
47201
|
if (globalEntries)
|
|
46419
47202
|
sections.push(globalEntries);
|
|
@@ -52133,7 +52916,7 @@ var init_tool_policy = __esm({
|
|
|
52133
52916
|
|
|
52134
52917
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
52135
52918
|
import { mkdirSync as mkdirSync19, existsSync as existsSync44, unlinkSync as unlinkSync10, readdirSync as readdirSync16, statSync as statSync14 } from "node:fs";
|
|
52136
|
-
import { join as join60, resolve as
|
|
52919
|
+
import { join as join60, resolve as resolve29 } from "node:path";
|
|
52137
52920
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
52138
52921
|
function convertMarkdownToTelegramHTML(md) {
|
|
52139
52922
|
let html = md;
|
|
@@ -52376,7 +53159,7 @@ with summary "no_reply" to silently skip without responding.
|
|
|
52376
53159
|
this.agentConfig = agentConfig;
|
|
52377
53160
|
this.repoRoot = repoRoot;
|
|
52378
53161
|
this.toolPolicyConfig = toolPolicyConfig;
|
|
52379
|
-
this.mediaCacheDir =
|
|
53162
|
+
this.mediaCacheDir = resolve29(repoRoot || ".", ".oa", "telegram-media-cache");
|
|
52380
53163
|
}
|
|
52381
53164
|
/** Set admin user ID filter */
|
|
52382
53165
|
setAdmin(userId) {
|
|
@@ -53612,7 +54395,7 @@ var init_braille_spinner = __esm({
|
|
|
53612
54395
|
// packages/cli/dist/tui/system-metrics.js
|
|
53613
54396
|
import { loadavg as loadavg3, cpus as cpus3, totalmem as totalmem4, freemem as freemem3, platform as platform4 } from "node:os";
|
|
53614
54397
|
import { exec as exec3 } from "node:child_process";
|
|
53615
|
-
import { readFile as
|
|
54398
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
53616
54399
|
function formatRate(bytesPerSec) {
|
|
53617
54400
|
if (bytesPerSec < 1024)
|
|
53618
54401
|
return `${Math.round(bytesPerSec)}B`;
|
|
@@ -53624,7 +54407,7 @@ function formatRate(bytesPerSec) {
|
|
|
53624
54407
|
}
|
|
53625
54408
|
async function readProcNetDev() {
|
|
53626
54409
|
try {
|
|
53627
|
-
const data = await
|
|
54410
|
+
const data = await readFile22("/proc/net/dev", "utf8");
|
|
53628
54411
|
let rxTotal = 0;
|
|
53629
54412
|
let txTotal = 0;
|
|
53630
54413
|
for (const line of data.split("\n")) {
|
|
@@ -53662,8 +54445,8 @@ async function collectNetworkMetrics() {
|
|
|
53662
54445
|
}
|
|
53663
54446
|
if (plat === "darwin") {
|
|
53664
54447
|
try {
|
|
53665
|
-
const output = await new Promise((
|
|
53666
|
-
exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
54448
|
+
const output = await new Promise((resolve33, reject) => {
|
|
54449
|
+
exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
|
|
53667
54450
|
});
|
|
53668
54451
|
let rxBytes = 0, txBytes = 0;
|
|
53669
54452
|
for (const line of output.split("\n")) {
|
|
@@ -53697,8 +54480,8 @@ async function collectGpuMetrics() {
|
|
|
53697
54480
|
if (_nvidiaSmiAvailable === false)
|
|
53698
54481
|
return noGpu;
|
|
53699
54482
|
try {
|
|
53700
|
-
const smi = await new Promise((
|
|
53701
|
-
exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
54483
|
+
const smi = await new Promise((resolve33, reject) => {
|
|
54484
|
+
exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
|
|
53702
54485
|
});
|
|
53703
54486
|
_nvidiaSmiAvailable = true;
|
|
53704
54487
|
const line = smi.trim().split("\n")[0];
|
|
@@ -56347,13 +57130,13 @@ var init_mouse_filter = __esm({
|
|
|
56347
57130
|
import * as readline2 from "node:readline";
|
|
56348
57131
|
import { Writable } from "node:stream";
|
|
56349
57132
|
import { cwd } from "node:process";
|
|
56350
|
-
import { resolve as
|
|
57133
|
+
import { resolve as resolve30, join as join61, dirname as dirname19, extname as extname10 } from "node:path";
|
|
56351
57134
|
import { createRequire as createRequire2 } from "node:module";
|
|
56352
57135
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
56353
57136
|
import { readFileSync as readFileSync34, writeFileSync as writeFileSync19, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync17, mkdirSync as mkdirSync20 } from "node:fs";
|
|
56354
57137
|
import { existsSync as existsSync45 } from "node:fs";
|
|
56355
57138
|
import { execSync as execSync30 } from "node:child_process";
|
|
56356
|
-
import { homedir as
|
|
57139
|
+
import { homedir as homedir16 } from "node:os";
|
|
56357
57140
|
function formatTimeAgo(date) {
|
|
56358
57141
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
56359
57142
|
if (seconds < 60)
|
|
@@ -56502,6 +57285,9 @@ function buildTools(repoRoot, config, contextWindowSize) {
|
|
|
56502
57285
|
new OpenCodeTool(repoRoot),
|
|
56503
57286
|
new FactoryTool(repoRoot),
|
|
56504
57287
|
new CronAgentTool(repoRoot),
|
|
57288
|
+
// Chunked file exploration + working notes
|
|
57289
|
+
new FileExploreTool(repoRoot),
|
|
57290
|
+
new WorkingNotesTool(),
|
|
56505
57291
|
// Nexus P2P networking + x402 micropayments
|
|
56506
57292
|
new NexusTool(repoRoot)
|
|
56507
57293
|
];
|
|
@@ -57651,7 +58437,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
57651
58437
|
} };
|
|
57652
58438
|
}
|
|
57653
58439
|
async function startInteractive(config, repoPath) {
|
|
57654
|
-
const repoRoot =
|
|
58440
|
+
const repoRoot = resolve30(repoPath ?? cwd());
|
|
57655
58441
|
const resumeFlag = process.env.__OA_RESUMED ?? "";
|
|
57656
58442
|
const isResumed = resumeFlag !== "";
|
|
57657
58443
|
const hasTaskToResume = resumeFlag === "1";
|
|
@@ -57823,14 +58609,14 @@ async function startInteractive(config, repoPath) {
|
|
|
57823
58609
|
renderInfo(msg);
|
|
57824
58610
|
statusBar.endContentWrite();
|
|
57825
58611
|
}
|
|
57826
|
-
}, () => new Promise((
|
|
58612
|
+
}, () => new Promise((resolve33) => {
|
|
57827
58613
|
depSudoPromptPending = true;
|
|
57828
58614
|
depSudoResolver = (pw) => {
|
|
57829
58615
|
depSudoPromptPending = false;
|
|
57830
58616
|
depSudoResolver = null;
|
|
57831
58617
|
if (pw)
|
|
57832
58618
|
sessionSudoPassword = pw;
|
|
57833
|
-
|
|
58619
|
+
resolve33(pw);
|
|
57834
58620
|
};
|
|
57835
58621
|
const pwPrompt1 = ` ${c2.bold(c2.yellow("\u{1F511} Password needed for dependency install:"))}
|
|
57836
58622
|
`;
|
|
@@ -58118,7 +58904,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
58118
58904
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
58119
58905
|
return [hits, line];
|
|
58120
58906
|
}
|
|
58121
|
-
const HISTORY_DIR = join61(
|
|
58907
|
+
const HISTORY_DIR = join61(homedir16(), ".open-agents");
|
|
58122
58908
|
const HISTORY_FILE = join61(HISTORY_DIR, "repl-history");
|
|
58123
58909
|
const MAX_HISTORY_LINES = 500;
|
|
58124
58910
|
let savedHistory = [];
|
|
@@ -59634,7 +60420,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
59634
60420
|
} catch {
|
|
59635
60421
|
}
|
|
59636
60422
|
try {
|
|
59637
|
-
const voiceDir2 = join61(
|
|
60423
|
+
const voiceDir2 = join61(homedir16(), ".open-agents", "voice");
|
|
59638
60424
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
59639
60425
|
for (const pf of voicePidFiles) {
|
|
59640
60426
|
const pidPath = join61(voiceDir2, pf);
|
|
@@ -60037,8 +60823,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
60037
60823
|
}
|
|
60038
60824
|
}
|
|
60039
60825
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
60040
|
-
const isImage = isImagePath(cleanPath) && existsSync45(
|
|
60041
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync45(
|
|
60826
|
+
const isImage = isImagePath(cleanPath) && existsSync45(resolve30(repoRoot, cleanPath));
|
|
60827
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync45(resolve30(repoRoot, cleanPath));
|
|
60042
60828
|
if (activeTask) {
|
|
60043
60829
|
if (activeTask.runner.isPaused) {
|
|
60044
60830
|
activeTask.runner.resume();
|
|
@@ -60046,7 +60832,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
60046
60832
|
}
|
|
60047
60833
|
if (isImage) {
|
|
60048
60834
|
try {
|
|
60049
|
-
const imgPath =
|
|
60835
|
+
const imgPath = resolve30(repoRoot, cleanPath);
|
|
60050
60836
|
const imgBuffer = readFileSync34(imgPath);
|
|
60051
60837
|
const base64 = imgBuffer.toString("base64");
|
|
60052
60838
|
const ext = extname10(cleanPath).toLowerCase();
|
|
@@ -60060,7 +60846,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
60060
60846
|
} else if (isMedia) {
|
|
60061
60847
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
60062
60848
|
const engine = getListenEngine();
|
|
60063
|
-
const result = await engine.transcribeFile(
|
|
60849
|
+
const result = await engine.transcribeFile(resolve30(repoRoot, cleanPath), repoRoot);
|
|
60064
60850
|
if (result) {
|
|
60065
60851
|
const transcript = `[Transcription of ${cleanPath}]
|
|
60066
60852
|
${result.text}`;
|
|
@@ -60204,7 +60990,7 @@ ${result.text}`;
|
|
|
60204
60990
|
const ext = cleanPath.toLowerCase().split(".").pop() || "";
|
|
60205
60991
|
if (cloneExts.includes("." + ext)) {
|
|
60206
60992
|
writeContent(() => renderInfo(`Setting voice clone reference: ${cleanPath}`));
|
|
60207
|
-
const msg = await voiceEngine.setCloneVoice(
|
|
60993
|
+
const msg = await voiceEngine.setCloneVoice(resolve30(repoRoot, cleanPath));
|
|
60208
60994
|
writeContent(() => renderInfo(msg));
|
|
60209
60995
|
showPrompt();
|
|
60210
60996
|
return;
|
|
@@ -60213,7 +60999,7 @@ ${result.text}`;
|
|
|
60213
60999
|
if (isMedia && fullInput === input) {
|
|
60214
61000
|
writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
|
|
60215
61001
|
const engine = getListenEngine();
|
|
60216
|
-
const result = await engine.transcribeFile(
|
|
61002
|
+
const result = await engine.transcribeFile(resolve30(repoRoot, cleanPath), repoRoot);
|
|
60217
61003
|
if (result) {
|
|
60218
61004
|
fullInput = `The user has provided an audio/video file: ${cleanPath}.
|
|
60219
61005
|
|
|
@@ -60499,7 +61285,7 @@ ${c2.dim("(Use /quit to exit)")}
|
|
|
60499
61285
|
};
|
|
60500
61286
|
}
|
|
60501
61287
|
async function runWithTUI(task, config, repoPath) {
|
|
60502
|
-
const repoRoot =
|
|
61288
|
+
const repoRoot = resolve30(repoPath ?? cwd());
|
|
60503
61289
|
const needsSetup = isFirstRun() || !await isModelAvailable(config);
|
|
60504
61290
|
if (needsSetup && config.backendType === "ollama") {
|
|
60505
61291
|
const setupModel = await runSetupWizard(config);
|
|
@@ -60882,7 +61668,7 @@ var init_run = __esm({
|
|
|
60882
61668
|
// packages/indexer/dist/codebase-indexer.js
|
|
60883
61669
|
import { glob } from "glob";
|
|
60884
61670
|
import ignore from "ignore";
|
|
60885
|
-
import { readFile as
|
|
61671
|
+
import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
|
|
60886
61672
|
import { createHash as createHash4 } from "node:crypto";
|
|
60887
61673
|
import { join as join62, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
|
|
60888
61674
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
@@ -60928,7 +61714,7 @@ var init_codebase_indexer = __esm({
|
|
|
60928
61714
|
const ig = ignore.default();
|
|
60929
61715
|
if (this.config.respectGitignore) {
|
|
60930
61716
|
try {
|
|
60931
|
-
const gitignoreContent = await
|
|
61717
|
+
const gitignoreContent = await readFile23(join62(this.config.rootDir, ".gitignore"), "utf-8");
|
|
60932
61718
|
ig.add(gitignoreContent);
|
|
60933
61719
|
} catch {
|
|
60934
61720
|
}
|
|
@@ -60948,7 +61734,7 @@ var init_codebase_indexer = __esm({
|
|
|
60948
61734
|
const fileStat = await stat4(fullPath);
|
|
60949
61735
|
if (fileStat.size > this.config.maxFileSize)
|
|
60950
61736
|
continue;
|
|
60951
|
-
const content = await
|
|
61737
|
+
const content = await readFile23(fullPath);
|
|
60952
61738
|
const hash = createHash4("sha256").update(content).digest("hex");
|
|
60953
61739
|
const ext = extname11(relativePath);
|
|
60954
61740
|
indexed.push({
|
|
@@ -61071,11 +61857,11 @@ var index_repo_exports = {};
|
|
|
61071
61857
|
__export(index_repo_exports, {
|
|
61072
61858
|
indexRepoCommand: () => indexRepoCommand
|
|
61073
61859
|
});
|
|
61074
|
-
import { resolve as
|
|
61860
|
+
import { resolve as resolve31 } from "node:path";
|
|
61075
61861
|
import { existsSync as existsSync46, statSync as statSync15 } from "node:fs";
|
|
61076
61862
|
import { cwd as cwd2 } from "node:process";
|
|
61077
61863
|
async function indexRepoCommand(opts, _config) {
|
|
61078
|
-
const repoRoot =
|
|
61864
|
+
const repoRoot = resolve31(opts.repoPath ?? cwd2());
|
|
61079
61865
|
printHeader("Index Repository");
|
|
61080
61866
|
printInfo(`Indexing: ${repoRoot}`);
|
|
61081
61867
|
if (!existsSync46(repoRoot)) {
|
|
@@ -61330,8 +62116,8 @@ var config_exports = {};
|
|
|
61330
62116
|
__export(config_exports, {
|
|
61331
62117
|
configCommand: () => configCommand
|
|
61332
62118
|
});
|
|
61333
|
-
import { join as join63, resolve as
|
|
61334
|
-
import { homedir as
|
|
62119
|
+
import { join as join63, resolve as resolve32 } from "node:path";
|
|
62120
|
+
import { homedir as homedir17 } from "node:os";
|
|
61335
62121
|
import { cwd as cwd3 } from "node:process";
|
|
61336
62122
|
function redactIfSensitive(key, value) {
|
|
61337
62123
|
if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
|
|
@@ -61363,7 +62149,7 @@ async function configCommand(opts, config) {
|
|
|
61363
62149
|
return handleShow(opts, config);
|
|
61364
62150
|
}
|
|
61365
62151
|
function handleShow(opts, config) {
|
|
61366
|
-
const repoRoot =
|
|
62152
|
+
const repoRoot = resolve32(opts.repoPath ?? cwd3());
|
|
61367
62153
|
printHeader("Configuration");
|
|
61368
62154
|
const resolved = resolveSettings(repoRoot);
|
|
61369
62155
|
printSection("Core Inference");
|
|
@@ -61413,7 +62199,7 @@ function handleShow(opts, config) {
|
|
|
61413
62199
|
}
|
|
61414
62200
|
}
|
|
61415
62201
|
printSection("Config File");
|
|
61416
|
-
printInfo(`~/.open-agents/config.json (${join63(
|
|
62202
|
+
printInfo(`~/.open-agents/config.json (${join63(homedir17(), ".open-agents", "config.json")})`);
|
|
61417
62203
|
printSection("Priority Chain");
|
|
61418
62204
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
61419
62205
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -61446,7 +62232,7 @@ function handleSet(opts, _config) {
|
|
|
61446
62232
|
process.exit(1);
|
|
61447
62233
|
}
|
|
61448
62234
|
if (opts.local) {
|
|
61449
|
-
const repoRoot =
|
|
62235
|
+
const repoRoot = resolve32(opts.repoPath ?? cwd3());
|
|
61450
62236
|
try {
|
|
61451
62237
|
initOaDirectory(repoRoot);
|
|
61452
62238
|
const coerced = coerceForSettings(key, value);
|
|
@@ -61644,7 +62430,7 @@ async function serveVllm(opts, config) {
|
|
|
61644
62430
|
await runVllmServer(args, opts.verbose ?? false);
|
|
61645
62431
|
}
|
|
61646
62432
|
async function runVllmServer(args, verbose) {
|
|
61647
|
-
return new Promise((
|
|
62433
|
+
return new Promise((resolve33, reject) => {
|
|
61648
62434
|
const child = spawn19("python", args, {
|
|
61649
62435
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
61650
62436
|
env: { ...process.env }
|
|
@@ -61679,10 +62465,10 @@ async function runVllmServer(args, verbose) {
|
|
|
61679
62465
|
child.once("exit", (code, signal) => {
|
|
61680
62466
|
if (signal) {
|
|
61681
62467
|
printInfo(`vLLM server stopped by signal ${signal}`);
|
|
61682
|
-
|
|
62468
|
+
resolve33();
|
|
61683
62469
|
} else if (code === 0) {
|
|
61684
62470
|
printSuccess("vLLM server exited cleanly");
|
|
61685
|
-
|
|
62471
|
+
resolve33();
|
|
61686
62472
|
} else {
|
|
61687
62473
|
printError(`vLLM server exited with code ${code}`);
|
|
61688
62474
|
reject(new Error(`vLLM exited with code ${code}`));
|