open-agents-ai 0.187.211 → 0.187.213
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 +793 -638
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -288395,12 +288395,16 @@ __export(overlay_lock_exports, {
|
|
|
288395
288395
|
enterOverlay: () => enterOverlay,
|
|
288396
288396
|
isOverlayActive: () => isOverlayActive,
|
|
288397
288397
|
leaveOverlay: () => leaveOverlay,
|
|
288398
|
+
onOverlayEnter: () => onOverlayEnter,
|
|
288398
288399
|
onOverlayLeave: () => onOverlayLeave,
|
|
288399
288400
|
overlayWrite: () => overlayWrite
|
|
288400
288401
|
});
|
|
288401
288402
|
function onOverlayLeave(cb) {
|
|
288402
288403
|
_onLeaveCallback = cb;
|
|
288403
288404
|
}
|
|
288405
|
+
function onOverlayEnter(cb) {
|
|
288406
|
+
_onEnterCallback = cb;
|
|
288407
|
+
}
|
|
288404
288408
|
function isOverlayActive() {
|
|
288405
288409
|
return _overlayActive;
|
|
288406
288410
|
}
|
|
@@ -288419,6 +288423,12 @@ function enterOverlay() {
|
|
|
288419
288423
|
_depth++;
|
|
288420
288424
|
if (_depth === 1) {
|
|
288421
288425
|
_overlayActive = true;
|
|
288426
|
+
if (_onEnterCallback) {
|
|
288427
|
+
try {
|
|
288428
|
+
_onEnterCallback();
|
|
288429
|
+
} catch {
|
|
288430
|
+
}
|
|
288431
|
+
}
|
|
288422
288432
|
_origStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
288423
288433
|
_origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
288424
288434
|
process.stdout.write = function(chunk, ...args) {
|
|
@@ -288456,7 +288466,7 @@ function leaveOverlay() {
|
|
|
288456
288466
|
_buffer = [];
|
|
288457
288467
|
}
|
|
288458
288468
|
}
|
|
288459
|
-
var _overlayActive, _depth, _buffer, _origStdoutWrite, _origStderrWrite, _onLeaveCallback;
|
|
288469
|
+
var _overlayActive, _depth, _buffer, _origStdoutWrite, _origStderrWrite, _onLeaveCallback, _onEnterCallback;
|
|
288460
288470
|
var init_overlay_lock = __esm({
|
|
288461
288471
|
"packages/cli/src/tui/overlay-lock.ts"() {
|
|
288462
288472
|
"use strict";
|
|
@@ -288466,6 +288476,288 @@ var init_overlay_lock = __esm({
|
|
|
288466
288476
|
_origStdoutWrite = null;
|
|
288467
288477
|
_origStderrWrite = null;
|
|
288468
288478
|
_onLeaveCallback = null;
|
|
288479
|
+
_onEnterCallback = null;
|
|
288480
|
+
}
|
|
288481
|
+
});
|
|
288482
|
+
|
|
288483
|
+
// packages/cli/src/tui/tui-tasks-renderer.ts
|
|
288484
|
+
var tui_tasks_renderer_exports = {};
|
|
288485
|
+
__export(tui_tasks_renderer_exports, {
|
|
288486
|
+
getTuiTasksScope: () => getTuiTasksScope,
|
|
288487
|
+
onTuiTasksHeightChange: () => onTuiTasksHeightChange,
|
|
288488
|
+
refreshTuiTasks: () => refreshTuiTasks,
|
|
288489
|
+
refreshTuiTasksSync: () => refreshTuiTasksSync,
|
|
288490
|
+
setTuiTasksEnabled: () => setTuiTasksEnabled,
|
|
288491
|
+
setTuiTasksScope: () => setTuiTasksScope,
|
|
288492
|
+
setTuiTasksSession: () => setTuiTasksSession,
|
|
288493
|
+
teardownTuiTasks: () => teardownTuiTasks
|
|
288494
|
+
});
|
|
288495
|
+
import { existsSync as existsSync57, readFileSync as readFileSync43, watch as fsWatch2 } from "node:fs";
|
|
288496
|
+
import { join as join74 } from "node:path";
|
|
288497
|
+
import { homedir as homedir24 } from "node:os";
|
|
288498
|
+
function panelEffectivelyVisible() {
|
|
288499
|
+
return _enabled && !_scopeOverlayActive && !_scopeNeovimActive && _scopeMainViewActive;
|
|
288500
|
+
}
|
|
288501
|
+
function todoDir2() {
|
|
288502
|
+
return join74(homedir24(), ".open-agents", "todos");
|
|
288503
|
+
}
|
|
288504
|
+
function todoPath2(sessionId) {
|
|
288505
|
+
const safe = sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
288506
|
+
return join74(todoDir2(), `${safe}.json`);
|
|
288507
|
+
}
|
|
288508
|
+
function setTuiTasksSession(sessionId) {
|
|
288509
|
+
if (sessionId === _activeSessionId) return;
|
|
288510
|
+
_activeSessionId = sessionId || null;
|
|
288511
|
+
if (_watcher) {
|
|
288512
|
+
try {
|
|
288513
|
+
_watcher.close();
|
|
288514
|
+
} catch {
|
|
288515
|
+
}
|
|
288516
|
+
_watcher = null;
|
|
288517
|
+
}
|
|
288518
|
+
if (!_activeSessionId) {
|
|
288519
|
+
_lastTodos = [];
|
|
288520
|
+
applyHeightChange(0);
|
|
288521
|
+
return;
|
|
288522
|
+
}
|
|
288523
|
+
loadTodos();
|
|
288524
|
+
installWatcher();
|
|
288525
|
+
scheduleRedraw();
|
|
288526
|
+
}
|
|
288527
|
+
function onTuiTasksHeightChange(cb) {
|
|
288528
|
+
_onResizeChange = cb;
|
|
288529
|
+
}
|
|
288530
|
+
function setTuiTasksEnabled(enabled2) {
|
|
288531
|
+
_enabled = enabled2;
|
|
288532
|
+
scheduleRedraw();
|
|
288533
|
+
}
|
|
288534
|
+
function setTuiTasksScope(scope) {
|
|
288535
|
+
let changed = false;
|
|
288536
|
+
if (scope.overlayActive !== void 0 && scope.overlayActive !== _scopeOverlayActive) {
|
|
288537
|
+
_scopeOverlayActive = scope.overlayActive;
|
|
288538
|
+
changed = true;
|
|
288539
|
+
}
|
|
288540
|
+
if (scope.mainViewActive !== void 0 && scope.mainViewActive !== _scopeMainViewActive) {
|
|
288541
|
+
_scopeMainViewActive = scope.mainViewActive;
|
|
288542
|
+
changed = true;
|
|
288543
|
+
}
|
|
288544
|
+
if (scope.neovimActive !== void 0 && scope.neovimActive !== _scopeNeovimActive) {
|
|
288545
|
+
_scopeNeovimActive = scope.neovimActive;
|
|
288546
|
+
changed = true;
|
|
288547
|
+
}
|
|
288548
|
+
if (changed) {
|
|
288549
|
+
if (!panelEffectivelyVisible()) {
|
|
288550
|
+
clearLastPaintedRows();
|
|
288551
|
+
applyHeightChange(0);
|
|
288552
|
+
} else {
|
|
288553
|
+
scheduleRedraw();
|
|
288554
|
+
}
|
|
288555
|
+
}
|
|
288556
|
+
}
|
|
288557
|
+
function getTuiTasksScope() {
|
|
288558
|
+
return {
|
|
288559
|
+
enabled: _enabled,
|
|
288560
|
+
overlayActive: _scopeOverlayActive,
|
|
288561
|
+
mainViewActive: _scopeMainViewActive,
|
|
288562
|
+
neovimActive: _scopeNeovimActive,
|
|
288563
|
+
visible: panelEffectivelyVisible()
|
|
288564
|
+
};
|
|
288565
|
+
}
|
|
288566
|
+
function refreshTuiTasks() {
|
|
288567
|
+
if (!_activeSessionId) return;
|
|
288568
|
+
loadTodos();
|
|
288569
|
+
scheduleRedraw();
|
|
288570
|
+
}
|
|
288571
|
+
function refreshTuiTasksSync() {
|
|
288572
|
+
if (!_activeSessionId) return;
|
|
288573
|
+
loadTodos();
|
|
288574
|
+
if (!_enabled) return;
|
|
288575
|
+
_redrawScheduled = false;
|
|
288576
|
+
render();
|
|
288577
|
+
}
|
|
288578
|
+
function teardownTuiTasks() {
|
|
288579
|
+
if (_watcher) {
|
|
288580
|
+
try {
|
|
288581
|
+
_watcher.close();
|
|
288582
|
+
} catch {
|
|
288583
|
+
}
|
|
288584
|
+
_watcher = null;
|
|
288585
|
+
}
|
|
288586
|
+
_activeSessionId = null;
|
|
288587
|
+
_lastTodos = [];
|
|
288588
|
+
applyHeightChange(0);
|
|
288589
|
+
}
|
|
288590
|
+
function installWatcher() {
|
|
288591
|
+
if (!_activeSessionId) return;
|
|
288592
|
+
try {
|
|
288593
|
+
_watcher = fsWatch2(todoDir2(), { persistent: false }, (_evt, fname) => {
|
|
288594
|
+
if (!fname || !_activeSessionId) return;
|
|
288595
|
+
const expected = `${_activeSessionId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
|
|
288596
|
+
if (fname !== expected) return;
|
|
288597
|
+
loadTodos();
|
|
288598
|
+
scheduleRedraw();
|
|
288599
|
+
});
|
|
288600
|
+
} catch {
|
|
288601
|
+
}
|
|
288602
|
+
}
|
|
288603
|
+
function loadTodos() {
|
|
288604
|
+
if (!_activeSessionId) {
|
|
288605
|
+
_lastTodos = [];
|
|
288606
|
+
return;
|
|
288607
|
+
}
|
|
288608
|
+
try {
|
|
288609
|
+
const fp = todoPath2(_activeSessionId);
|
|
288610
|
+
if (!existsSync57(fp)) {
|
|
288611
|
+
_lastTodos = [];
|
|
288612
|
+
return;
|
|
288613
|
+
}
|
|
288614
|
+
const parsed = JSON.parse(readFileSync43(fp, "utf-8"));
|
|
288615
|
+
_lastTodos = Array.isArray(parsed) ? parsed : [];
|
|
288616
|
+
} catch {
|
|
288617
|
+
_lastTodos = [];
|
|
288618
|
+
}
|
|
288619
|
+
}
|
|
288620
|
+
function scheduleRedraw() {
|
|
288621
|
+
if (_redrawScheduled || !_enabled) return;
|
|
288622
|
+
_redrawScheduled = true;
|
|
288623
|
+
setImmediate(() => {
|
|
288624
|
+
_redrawScheduled = false;
|
|
288625
|
+
render();
|
|
288626
|
+
});
|
|
288627
|
+
}
|
|
288628
|
+
function computeTargetHeight() {
|
|
288629
|
+
if (!panelEffectivelyVisible()) return 0;
|
|
288630
|
+
if (!_lastTodos || _lastTodos.length === 0) return 0;
|
|
288631
|
+
const itemRows = Math.min(_lastTodos.length, MAX_VISIBLE_ROWS - 1);
|
|
288632
|
+
return 1 + itemRows;
|
|
288633
|
+
}
|
|
288634
|
+
function applyHeightChange(nextHeight) {
|
|
288635
|
+
const changed = setTasksHeight(nextHeight);
|
|
288636
|
+
if (changed) {
|
|
288637
|
+
notifyLayoutResize();
|
|
288638
|
+
}
|
|
288639
|
+
if (_onResizeChange) {
|
|
288640
|
+
try {
|
|
288641
|
+
_onResizeChange(nextHeight);
|
|
288642
|
+
} catch {
|
|
288643
|
+
}
|
|
288644
|
+
}
|
|
288645
|
+
}
|
|
288646
|
+
function statusToAnsi(status) {
|
|
288647
|
+
switch (status) {
|
|
288648
|
+
case "completed":
|
|
288649
|
+
return { mark: "◉", color: MUTED_GREEN, box: GREEN };
|
|
288650
|
+
case "in_progress":
|
|
288651
|
+
return { mark: "◐", color: GOLD, box: GOLD };
|
|
288652
|
+
case "blocked":
|
|
288653
|
+
return { mark: "◍", color: RED, box: RED };
|
|
288654
|
+
default:
|
|
288655
|
+
return { mark: "〇", color: GREY, box: GREY };
|
|
288656
|
+
}
|
|
288657
|
+
}
|
|
288658
|
+
function truncate2(s2, max) {
|
|
288659
|
+
if (s2.length <= max) return s2.padEnd(max, " ");
|
|
288660
|
+
return s2.slice(0, Math.max(0, max - 1)) + "…";
|
|
288661
|
+
}
|
|
288662
|
+
function render() {
|
|
288663
|
+
if (!_enabled) return;
|
|
288664
|
+
if (!panelEffectivelyVisible()) {
|
|
288665
|
+
clearLastPaintedRows();
|
|
288666
|
+
applyHeightChange(0);
|
|
288667
|
+
return;
|
|
288668
|
+
}
|
|
288669
|
+
const target = computeTargetHeight();
|
|
288670
|
+
applyHeightChange(target);
|
|
288671
|
+
if (target === 0) {
|
|
288672
|
+
clearLastPaintedRows();
|
|
288673
|
+
return;
|
|
288674
|
+
}
|
|
288675
|
+
const L = layout();
|
|
288676
|
+
const cols = Math.max(20, termCols());
|
|
288677
|
+
const completed = _lastTodos.filter((t2) => t2.status === "completed").length;
|
|
288678
|
+
const total = _lastTodos.length;
|
|
288679
|
+
const headerColor = completed === total ? GREEN : GOLD;
|
|
288680
|
+
const lines = [];
|
|
288681
|
+
const headerText = `tasks ${headerColor}${completed}/${total}${RESET}${DIM_LABEL} (todo_write)${RESET}`;
|
|
288682
|
+
lines.push(headerText);
|
|
288683
|
+
const visible = _lastTodos.slice(0, MAX_VISIBLE_ROWS - 1);
|
|
288684
|
+
for (const t2 of visible) {
|
|
288685
|
+
const { mark, color } = statusToAnsi(t2.status);
|
|
288686
|
+
const contentWidth = Math.max(4, cols - 8);
|
|
288687
|
+
const contentText = t2.content + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
|
|
288688
|
+
const truncated = truncate2(contentText, contentWidth);
|
|
288689
|
+
lines.push(`${color}${mark}${RESET} ${color}${truncated}${RESET}`);
|
|
288690
|
+
}
|
|
288691
|
+
if (_lastTodos.length > visible.length) {
|
|
288692
|
+
const more = _lastTodos.length - visible.length;
|
|
288693
|
+
lines[lines.length - 1] = `${DIM_LABEL}… +${more} more${RESET}`;
|
|
288694
|
+
}
|
|
288695
|
+
let out = HIDE + SAVE;
|
|
288696
|
+
const newTop = L.tasksTop;
|
|
288697
|
+
const newBottom = Math.min(L.tasksBottom, L.tasksTop + lines.length - 1);
|
|
288698
|
+
if (_lastPaintedTop >= 0 && _lastPaintedBottom >= _lastPaintedTop) {
|
|
288699
|
+
for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
|
|
288700
|
+
if (row >= newTop && row <= newBottom) continue;
|
|
288701
|
+
out += `\x1B[${row};1H${CLEAR_LINE}`;
|
|
288702
|
+
}
|
|
288703
|
+
}
|
|
288704
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
288705
|
+
const row = L.tasksTop + i2;
|
|
288706
|
+
if (row > L.tasksBottom) break;
|
|
288707
|
+
out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET}`;
|
|
288708
|
+
}
|
|
288709
|
+
out += RESTORE + SHOW;
|
|
288710
|
+
try {
|
|
288711
|
+
process.stdout.write(out);
|
|
288712
|
+
} catch {
|
|
288713
|
+
}
|
|
288714
|
+
_lastPaintedTop = newTop;
|
|
288715
|
+
_lastPaintedBottom = newBottom;
|
|
288716
|
+
}
|
|
288717
|
+
function clearLastPaintedRows() {
|
|
288718
|
+
if (_lastPaintedTop < 0 || _lastPaintedBottom < _lastPaintedTop) return;
|
|
288719
|
+
let out = HIDE + SAVE;
|
|
288720
|
+
for (let row = _lastPaintedTop; row <= _lastPaintedBottom; row++) {
|
|
288721
|
+
out += `\x1B[${row};1H${CLEAR_LINE}`;
|
|
288722
|
+
}
|
|
288723
|
+
out += RESTORE + SHOW;
|
|
288724
|
+
try {
|
|
288725
|
+
process.stdout.write(out);
|
|
288726
|
+
} catch {
|
|
288727
|
+
}
|
|
288728
|
+
_lastPaintedTop = -1;
|
|
288729
|
+
_lastPaintedBottom = -1;
|
|
288730
|
+
}
|
|
288731
|
+
var _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, _lastPaintedTop, _lastPaintedBottom, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET, BG, DIM_LABEL, GOLD, GREEN, MUTED_GREEN, GREY, RED;
|
|
288732
|
+
var init_tui_tasks_renderer = __esm({
|
|
288733
|
+
"packages/cli/src/tui/tui-tasks-renderer.ts"() {
|
|
288734
|
+
"use strict";
|
|
288735
|
+
init_layout2();
|
|
288736
|
+
_activeSessionId = null;
|
|
288737
|
+
_watcher = null;
|
|
288738
|
+
_lastTodos = [];
|
|
288739
|
+
_enabled = true;
|
|
288740
|
+
_redrawScheduled = false;
|
|
288741
|
+
_onResizeChange = null;
|
|
288742
|
+
_scopeOverlayActive = false;
|
|
288743
|
+
_scopeMainViewActive = true;
|
|
288744
|
+
_scopeNeovimActive = false;
|
|
288745
|
+
_lastPaintedTop = -1;
|
|
288746
|
+
_lastPaintedBottom = -1;
|
|
288747
|
+
MAX_VISIBLE_ROWS = 8;
|
|
288748
|
+
SAVE = "\x1B[s";
|
|
288749
|
+
RESTORE = "\x1B[u";
|
|
288750
|
+
HIDE = "\x1B[?25l";
|
|
288751
|
+
SHOW = "\x1B[?25h";
|
|
288752
|
+
CLEAR_LINE = "\x1B[2K";
|
|
288753
|
+
RESET = "\x1B[0m";
|
|
288754
|
+
BG = "\x1B[48;2;23;23;26m";
|
|
288755
|
+
DIM_LABEL = "\x1B[38;2;68;68;68m";
|
|
288756
|
+
GOLD = "\x1B[38;2;178;146;10m";
|
|
288757
|
+
GREEN = "\x1B[38;2;95;165;95m";
|
|
288758
|
+
MUTED_GREEN = "\x1B[38;2;74;122;74m";
|
|
288759
|
+
GREY = "\x1B[38;2;102;102;102m";
|
|
288760
|
+
RED = "\x1B[38;2;178;95;95m";
|
|
288469
288761
|
}
|
|
288470
288762
|
});
|
|
288471
288763
|
|
|
@@ -288479,7 +288771,7 @@ __export(status_bar_exports, {
|
|
|
288479
288771
|
setTerminalTitle: () => setTerminalTitle,
|
|
288480
288772
|
unlockFooterRedraws: () => unlockFooterRedraws
|
|
288481
288773
|
});
|
|
288482
|
-
import { readFileSync as
|
|
288774
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
288483
288775
|
function lockFooterRedraws() {
|
|
288484
288776
|
_globalFooterLock = true;
|
|
288485
288777
|
}
|
|
@@ -288499,7 +288791,7 @@ function setTerminalTitle(task, version4) {
|
|
|
288499
288791
|
const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
|
|
288500
288792
|
process.stdout.write(`\x1B]2;${title}\x07`);
|
|
288501
288793
|
}
|
|
288502
|
-
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock,
|
|
288794
|
+
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
|
|
288503
288795
|
var init_status_bar = __esm({
|
|
288504
288796
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
288505
288797
|
"use strict";
|
|
@@ -288677,7 +288969,7 @@ var init_status_bar = __esm({
|
|
|
288677
288969
|
BOX_H = "─";
|
|
288678
288970
|
BOX_V = "│";
|
|
288679
288971
|
_globalFooterLock = false;
|
|
288680
|
-
|
|
288972
|
+
RESET2 = "\x1B[0m";
|
|
288681
288973
|
CURSOR_BLINK_BLOCK = "\x1B[1 q";
|
|
288682
288974
|
_isWindows = process.platform === "win32";
|
|
288683
288975
|
StatusBar = class _StatusBar {
|
|
@@ -288731,6 +289023,12 @@ var init_status_bar = __esm({
|
|
|
288731
289023
|
_prevTermCols = 0;
|
|
288732
289024
|
/** Debounce timer for resize events — prevents separator stacking during drag */
|
|
288733
289025
|
_resizeTimer = null;
|
|
289026
|
+
/** WO-TASK-02 — callback fired at the END of _handleResizeImmediate so
|
|
289027
|
+
* the tasks renderer can repaint AFTER the clear loop wipes the zone.
|
|
289028
|
+
* Without this, refreshTuiTasks() called from interactive.ts's resize
|
|
289029
|
+
* handler runs BEFORE the debounced _handleResizeImmediate and gets
|
|
289030
|
+
* clobbered. Wired in interactive.ts via setOnResizeFinalized(). */
|
|
289031
|
+
_onResizeFinalized = null;
|
|
288734
289032
|
/** True while resize is in-flight (between first SIGWINCH and debounce settle).
|
|
288735
289033
|
* Suppresses ALL footer renders to prevent separator debris at intermediate sizes. */
|
|
288736
289034
|
_resizing = false;
|
|
@@ -289036,14 +289334,14 @@ var init_status_bar = __esm({
|
|
|
289036
289334
|
const hdrRow = layout().headerContent;
|
|
289037
289335
|
let buf = "\x1B7";
|
|
289038
289336
|
buf += `\x1B[${hdrRow};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
289039
|
-
buf += `${BOX_FG}│${
|
|
289337
|
+
buf += `${BOX_FG}│${RESET2}${PANEL_BG_SEQ}`;
|
|
289040
289338
|
buf += leftArrow;
|
|
289041
289339
|
buf += ` `;
|
|
289042
289340
|
buf += `\x1B[38;5;${TEXT_PRIMARY}m${PANEL_BG_SEQ}`;
|
|
289043
289341
|
buf += content;
|
|
289044
289342
|
buf += `\x1B[${hdrRow};${w - 1}H`;
|
|
289045
289343
|
buf += rightArrow;
|
|
289046
|
-
buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${
|
|
289344
|
+
buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${RESET2}`;
|
|
289047
289345
|
buf += "\x1B8";
|
|
289048
289346
|
this.termWrite(buf);
|
|
289049
289347
|
}
|
|
@@ -289433,7 +289731,7 @@ var init_status_bar = __esm({
|
|
|
289433
289731
|
if (nexusDir) {
|
|
289434
289732
|
try {
|
|
289435
289733
|
const metricsPath = nexusDir + "/remote-metrics.json";
|
|
289436
|
-
const raw =
|
|
289734
|
+
const raw = readFileSync44(metricsPath, "utf8");
|
|
289437
289735
|
const cached = JSON.parse(raw);
|
|
289438
289736
|
if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
|
|
289439
289737
|
const m2 = cached.data;
|
|
@@ -289968,6 +290266,8 @@ var init_status_bar = __esm({
|
|
|
289968
290266
|
this._activeViewId = id;
|
|
289969
290267
|
this._contentLines = view.contentLines;
|
|
289970
290268
|
this._contentScrollOffset = view.scrollOffset;
|
|
290269
|
+
Promise.resolve().then(() => (init_tui_tasks_renderer(), tui_tasks_renderer_exports)).then((m2) => m2.setTuiTasksScope({ mainViewActive: id === "main" })).catch(() => {
|
|
290270
|
+
});
|
|
289971
290271
|
this.repaintContent();
|
|
289972
290272
|
this.renderAgentTabs();
|
|
289973
290273
|
}
|
|
@@ -290116,11 +290416,11 @@ var init_status_bar = __esm({
|
|
|
290116
290416
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
290117
290417
|
const row = pos.inputStartRow + i2;
|
|
290118
290418
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
290119
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${
|
|
290419
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${RESET2}`;
|
|
290120
290420
|
}
|
|
290121
290421
|
const boxInnerP = w - 2;
|
|
290122
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerP))}${BOX_BR}${
|
|
290123
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
290422
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerP))}${BOX_BR}${RESET2}`;
|
|
290423
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}\x1B[?7h\x1B[${pos.scrollEnd};1H`;
|
|
290124
290424
|
this.termWrite(buf);
|
|
290125
290425
|
} else {
|
|
290126
290426
|
this.applyScrollRegion(true);
|
|
@@ -290135,6 +290435,18 @@ var init_status_bar = __esm({
|
|
|
290135
290435
|
this.renderFooterAndPositionInput();
|
|
290136
290436
|
if (this._bannerRefresh) this._bannerRefresh();
|
|
290137
290437
|
}
|
|
290438
|
+
if (this._onResizeFinalized) {
|
|
290439
|
+
try {
|
|
290440
|
+
this._onResizeFinalized();
|
|
290441
|
+
} catch {
|
|
290442
|
+
}
|
|
290443
|
+
}
|
|
290444
|
+
}
|
|
290445
|
+
/** Register a callback that fires AT THE END of _handleResizeImmediate.
|
|
290446
|
+
* Use this from interactive.ts to repaint the tasks panel after the
|
|
290447
|
+
* debounced clear/redraw cycle finishes. */
|
|
290448
|
+
setOnResizeFinalized(cb) {
|
|
290449
|
+
this._onResizeFinalized = cb;
|
|
290138
290450
|
}
|
|
290139
290451
|
/**
|
|
290140
290452
|
* Update the top boundary of the scroll region (e.g. after carousel retirement).
|
|
@@ -290262,7 +290574,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290262
290574
|
process.stdout.write = this._origWrite;
|
|
290263
290575
|
this._origWrite = null;
|
|
290264
290576
|
}
|
|
290265
|
-
process.stdout.write(
|
|
290577
|
+
process.stdout.write(RESET2);
|
|
290266
290578
|
this._brailleSpinner.setMetrics({ isStreaming: false });
|
|
290267
290579
|
this.renderFooterAndPositionInput();
|
|
290268
290580
|
this.scheduleMouseIdle();
|
|
@@ -290918,19 +291230,19 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290918
291230
|
const inputWrap = this.wrapInput(w);
|
|
290919
291231
|
let buf = "\x1B[?7l";
|
|
290920
291232
|
const boxInner = w - 2;
|
|
290921
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_TR}${
|
|
291233
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_TR}${RESET2}`;
|
|
290922
291234
|
const spacerRow = pos.inputStartRow - 1;
|
|
290923
291235
|
if (spacerRow >= this.scrollRegionTop) {
|
|
290924
|
-
buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
291236
|
+
buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
|
|
290925
291237
|
}
|
|
290926
291238
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
290927
291239
|
const row = pos.inputStartRow + 1 + i2;
|
|
290928
291240
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
290929
291241
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
290930
291242
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
290931
|
-
buf += `${BOX_FG}${BOX_V}${
|
|
291243
|
+
buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
|
|
290932
291244
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
290933
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291245
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
290934
291246
|
}
|
|
290935
291247
|
const cursorTermRow = pos.inputStartRow + 1 + inputWrap.cursorRow;
|
|
290936
291248
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
@@ -290942,17 +291254,17 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290942
291254
|
const fg2 = isHighlighted ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
|
|
290943
291255
|
const slash = isHighlighted ? `\x1B[38;5;245m` : `\x1B[38;5;${TEXT_DIM}m`;
|
|
290944
291256
|
const marker = isHighlighted ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
|
|
290945
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${
|
|
291257
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}`;
|
|
290946
291258
|
buf += `${bg} ${marker}${slash}/${fg2}${cmd}`;
|
|
290947
291259
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
290948
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291260
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
290949
291261
|
}
|
|
290950
291262
|
const suggestBottomRow = pos.suggestStartRow + this._suggestions.length;
|
|
290951
|
-
buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${
|
|
291263
|
+
buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${RESET2}`;
|
|
290952
291264
|
} else {
|
|
290953
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${
|
|
291265
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${RESET2}`;
|
|
290954
291266
|
}
|
|
290955
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
291267
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}`;
|
|
290956
291268
|
buf += "\x1B[?7h";
|
|
290957
291269
|
if (this.writeDepth === 0) {
|
|
290958
291270
|
buf += `\x1B[${cursorTermRow};${inputWrap.cursorCol}H${CURSOR_BLINK_BLOCK}\x1B[?25h`;
|
|
@@ -290985,7 +291297,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290985
291297
|
const pos = this.rowPositions(termRows());
|
|
290986
291298
|
let buf = "\x1B7\x1B[?7l";
|
|
290987
291299
|
if (pos.tabBarRow > 0) {
|
|
290988
|
-
buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
291300
|
+
buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
|
|
290989
291301
|
}
|
|
290990
291302
|
const boxInnerR = w - 2;
|
|
290991
291303
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
@@ -290995,14 +291307,14 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290995
291307
|
const isHl = si === this._suggestIndex;
|
|
290996
291308
|
const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
|
|
290997
291309
|
const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
|
|
290998
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${
|
|
290999
|
-
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291310
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
|
|
291311
|
+
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
291000
291312
|
}
|
|
291001
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${
|
|
291313
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${RESET2}`;
|
|
291002
291314
|
} else {
|
|
291003
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${
|
|
291315
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${RESET2}`;
|
|
291004
291316
|
}
|
|
291005
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
291317
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}\x1B[?7h\x1B8` + // DEC restore cursor
|
|
291006
291318
|
(this.writeDepth === 0 ? `${CURSOR_BLINK_BLOCK}\x1B[?25h` : "");
|
|
291007
291319
|
this.termWrite(buf);
|
|
291008
291320
|
if (pos.tabBarRow > 0) this.renderAgentTabs();
|
|
@@ -291036,16 +291348,16 @@ ${CONTENT_BG_SEQ}`);
|
|
|
291036
291348
|
}
|
|
291037
291349
|
buf += "\x1B[?7l";
|
|
291038
291350
|
const boxInnerH = w - 2;
|
|
291039
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInnerH))}${BOX_TR}${
|
|
291351
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInnerH))}${BOX_TR}${RESET2}`;
|
|
291040
291352
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
291041
291353
|
const row = pos.inputStartRow + 1 + i2;
|
|
291042
291354
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
291043
291355
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
291044
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${
|
|
291356
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
291045
291357
|
}
|
|
291046
291358
|
const boxInnerS = w - 2;
|
|
291047
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerS))}${BOX_BR}${
|
|
291048
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
291359
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerS))}${BOX_BR}${RESET2}`;
|
|
291360
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}`;
|
|
291049
291361
|
buf += "\x1B[?7h";
|
|
291050
291362
|
buf += "\x1B8";
|
|
291051
291363
|
if (heightDelta > 0) {
|
|
@@ -291062,9 +291374,9 @@ ${CONTENT_BG_SEQ}`);
|
|
|
291062
291374
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
291063
291375
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
291064
291376
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
291065
|
-
buf += `${BOX_FG}${BOX_V}${
|
|
291377
|
+
buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
|
|
291066
291378
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
291067
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291379
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
291068
291380
|
}
|
|
291069
291381
|
buf += "\x1B[?7h";
|
|
291070
291382
|
this.termWrite(buf);
|
|
@@ -291920,9 +292232,9 @@ __export(personaplex_exports, {
|
|
|
291920
292232
|
startPersonaPlexDaemon: () => startPersonaPlexDaemon,
|
|
291921
292233
|
stopPersonaPlex: () => stopPersonaPlex
|
|
291922
292234
|
});
|
|
291923
|
-
import { existsSync as
|
|
291924
|
-
import { join as
|
|
291925
|
-
import { homedir as
|
|
292235
|
+
import { existsSync as existsSync58, writeFileSync as writeFileSync29, readFileSync as readFileSync45, mkdirSync as mkdirSync32, copyFileSync as copyFileSync2, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
|
|
292236
|
+
import { join as join75, dirname as dirname21 } from "node:path";
|
|
292237
|
+
import { homedir as homedir25 } from "node:os";
|
|
291926
292238
|
import { execSync as execSync47, spawn as spawn21 } from "node:child_process";
|
|
291927
292239
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
291928
292240
|
function execAsync(cmd, opts = {}) {
|
|
@@ -291954,7 +292266,7 @@ function selectWeightTier(vramGB) {
|
|
|
291954
292266
|
}
|
|
291955
292267
|
function detectJetson() {
|
|
291956
292268
|
try {
|
|
291957
|
-
const model =
|
|
292269
|
+
const model = readFileSync45("/proc/device-tree/model", "utf8").replace(/\0/g, "").trim();
|
|
291958
292270
|
if (/jetson|orin|tegra/i.test(model)) {
|
|
291959
292271
|
const memInfo = execSync47("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
|
|
291960
292272
|
const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
|
|
@@ -292031,8 +292343,8 @@ function fileLink2(filePath, label) {
|
|
|
292031
292343
|
return `\x1B]8;;${url}\x1B\\${text}\x1B]8;;\x1B\\`;
|
|
292032
292344
|
}
|
|
292033
292345
|
function isPersonaPlexRunning() {
|
|
292034
|
-
if (!
|
|
292035
|
-
const pid = parseInt(
|
|
292346
|
+
if (!existsSync58(PID_FILE)) return false;
|
|
292347
|
+
const pid = parseInt(readFileSync45(PID_FILE, "utf8").trim(), 10);
|
|
292036
292348
|
if (isNaN(pid) || pid <= 0) return false;
|
|
292037
292349
|
try {
|
|
292038
292350
|
process.kill(pid, 0);
|
|
@@ -292043,18 +292355,18 @@ function isPersonaPlexRunning() {
|
|
|
292043
292355
|
}
|
|
292044
292356
|
function getPersonaPlexWSUrl() {
|
|
292045
292357
|
if (!isPersonaPlexRunning()) return null;
|
|
292046
|
-
if (!
|
|
292047
|
-
const port = parseInt(
|
|
292358
|
+
if (!existsSync58(PORT_FILE)) return null;
|
|
292359
|
+
const port = parseInt(readFileSync45(PORT_FILE, "utf8").trim(), 10);
|
|
292048
292360
|
return isNaN(port) ? null : `wss://127.0.0.1:${port}`;
|
|
292049
292361
|
}
|
|
292050
292362
|
function isPersonaPlexInstalled() {
|
|
292051
|
-
return
|
|
292363
|
+
return existsSync58(join75(PERSONAPLEX_DIR, "model_ready"));
|
|
292052
292364
|
}
|
|
292053
292365
|
function getWeightTier() {
|
|
292054
292366
|
const detected = detectPersonaPlexCapability();
|
|
292055
|
-
const tierFile =
|
|
292056
|
-
if (
|
|
292057
|
-
const saved =
|
|
292367
|
+
const tierFile = join75(PERSONAPLEX_DIR, "weight_tier");
|
|
292368
|
+
if (existsSync58(tierFile)) {
|
|
292369
|
+
const saved = readFileSync45(tierFile, "utf8").trim();
|
|
292058
292370
|
if (saved in WEIGHT_REPOS) {
|
|
292059
292371
|
const vram = detected.vramGB;
|
|
292060
292372
|
if (saved === "nf4-distilled" && vram < 24) {
|
|
@@ -292080,8 +292392,8 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292080
292392
|
}
|
|
292081
292393
|
const isAarch64 = arch2 === "aarch64" || arch2 === "arm64";
|
|
292082
292394
|
if (isAarch64) log22(`Detected ARM64 platform (${arch2}) — Jetson/ARM install path`);
|
|
292083
|
-
const venvDir =
|
|
292084
|
-
if (!
|
|
292395
|
+
const venvDir = join75(PERSONAPLEX_DIR, "venv");
|
|
292396
|
+
if (!existsSync58(venvDir)) {
|
|
292085
292397
|
log22("Creating Python virtual environment...");
|
|
292086
292398
|
try {
|
|
292087
292399
|
const ssp = isAarch64 ? " --system-site-packages" : "";
|
|
@@ -292091,8 +292403,8 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292091
292403
|
return false;
|
|
292092
292404
|
}
|
|
292093
292405
|
}
|
|
292094
|
-
const pip = process.platform === "win32" ?
|
|
292095
|
-
const python = process.platform === "win32" ?
|
|
292406
|
+
const pip = process.platform === "win32" ? join75(venvDir, "Scripts", "pip.exe") : join75(venvDir, "bin", "pip");
|
|
292407
|
+
const python = process.platform === "win32" ? join75(venvDir, "Scripts", "python.exe") : join75(venvDir, "bin", "python3");
|
|
292096
292408
|
log22("Checking system dependencies (libopus)...");
|
|
292097
292409
|
try {
|
|
292098
292410
|
if (process.platform === "linux") {
|
|
@@ -292122,9 +292434,9 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292122
292434
|
}
|
|
292123
292435
|
}
|
|
292124
292436
|
log22("Installing PersonaPlex (moshi package)...");
|
|
292125
|
-
const repoDir =
|
|
292437
|
+
const repoDir = join75(PERSONAPLEX_DIR, "personaplex-repo");
|
|
292126
292438
|
try {
|
|
292127
|
-
if (!
|
|
292439
|
+
if (!existsSync58(repoDir)) {
|
|
292128
292440
|
await execAsync(
|
|
292129
292441
|
`git clone https://github.com/NVIDIA/personaplex.git "${repoDir}"`,
|
|
292130
292442
|
{ timeout: 12e4 }
|
|
@@ -292148,7 +292460,7 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292148
292460
|
if (isAarch64) {
|
|
292149
292461
|
log22("ARM64: Installing moshi (--no-deps to preserve JetPack torch)...");
|
|
292150
292462
|
await execAsync(
|
|
292151
|
-
`"${pip}" install --quiet --no-deps "${
|
|
292463
|
+
`"${pip}" install --quiet --no-deps "${join75(repoDir, "moshi")}/."`,
|
|
292152
292464
|
{ timeout: 3e5 }
|
|
292153
292465
|
);
|
|
292154
292466
|
log22("ARM64: Installing remaining moshi dependencies...");
|
|
@@ -292158,7 +292470,7 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292158
292470
|
);
|
|
292159
292471
|
} else {
|
|
292160
292472
|
await execAsync(
|
|
292161
|
-
`"${pip}" install --quiet "${
|
|
292473
|
+
`"${pip}" install --quiet "${join75(repoDir, "moshi")}/."`,
|
|
292162
292474
|
{ timeout: 6e5 }
|
|
292163
292475
|
// 10 min — torch download is ~2.5GB
|
|
292164
292476
|
);
|
|
@@ -292176,16 +292488,16 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292176
292488
|
}
|
|
292177
292489
|
return false;
|
|
292178
292490
|
}
|
|
292179
|
-
const serverPy =
|
|
292491
|
+
const serverPy = join75(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
|
|
292180
292492
|
try {
|
|
292181
292493
|
const sitePackages = execSync47(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
|
|
292182
292494
|
encoding: "utf8",
|
|
292183
292495
|
timeout: 5e3,
|
|
292184
292496
|
stdio: "pipe"
|
|
292185
292497
|
}).trim();
|
|
292186
|
-
const serverFile =
|
|
292187
|
-
if (
|
|
292188
|
-
let src2 =
|
|
292498
|
+
const serverFile = join75(sitePackages, "server.py");
|
|
292499
|
+
if (existsSync58(serverFile)) {
|
|
292500
|
+
let src2 = readFileSync45(serverFile, "utf8");
|
|
292189
292501
|
if (src2.includes('int(request["seed"])')) {
|
|
292190
292502
|
src2 = src2.replace('int(request["seed"])', 'int(request.query["seed"])');
|
|
292191
292503
|
writeFileSync29(serverFile, src2);
|
|
@@ -292200,9 +292512,9 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292200
292512
|
timeout: 5e3,
|
|
292201
292513
|
stdio: "pipe"
|
|
292202
292514
|
}).trim();
|
|
292203
|
-
const loadersFile =
|
|
292204
|
-
if (
|
|
292205
|
-
let src2 =
|
|
292515
|
+
const loadersFile = join75(sitePackages, "models", "loaders.py");
|
|
292516
|
+
if (existsSync58(loadersFile)) {
|
|
292517
|
+
let src2 = readFileSync45(loadersFile, "utf8");
|
|
292206
292518
|
if (!src2.includes("_dequantize_2bit_state_dict")) {
|
|
292207
292519
|
const dequantPatch = `
|
|
292208
292520
|
import math
|
|
@@ -292304,30 +292616,30 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292304
292616
|
timeout: 5e3,
|
|
292305
292617
|
stdio: "pipe"
|
|
292306
292618
|
}).trim();
|
|
292307
|
-
const hybridDest =
|
|
292308
|
-
const serverDest =
|
|
292309
|
-
if (!
|
|
292619
|
+
const hybridDest = join75(sitePackages2, "hybrid_agent.py");
|
|
292620
|
+
const serverDest = join75(sitePackages2, "server.py");
|
|
292621
|
+
if (!existsSync58(hybridDest) || !readFileSync45(hybridDest, "utf8").includes("OA_API_BASE")) {
|
|
292310
292622
|
log22("Deploying hybrid_agent.py (OA API integration)...");
|
|
292311
292623
|
try {
|
|
292312
292624
|
await execAsync(
|
|
292313
292625
|
`curl -sL "https://raw.githubusercontent.com/robit-man/personaplex/main/personaplex-setup/moshi/moshi/hybrid_agent.py" -o "${hybridDest}"`,
|
|
292314
292626
|
{ timeout: 3e4 }
|
|
292315
292627
|
);
|
|
292316
|
-
if (
|
|
292628
|
+
if (existsSync58(hybridDest) && readFileSync45(hybridDest, "utf8").includes("OA_API_BASE")) {
|
|
292317
292629
|
log22("hybrid_agent.py deployed (OA API + Ollama fallback).");
|
|
292318
292630
|
}
|
|
292319
292631
|
} catch {
|
|
292320
292632
|
log22("hybrid_agent.py download failed — hybrid mode will be disabled.");
|
|
292321
292633
|
}
|
|
292322
292634
|
}
|
|
292323
|
-
if (!
|
|
292635
|
+
if (!readFileSync45(serverDest, "utf8").includes("hybrid_agent")) {
|
|
292324
292636
|
log22("Deploying patched server.py (hybrid mode + API endpoints)...");
|
|
292325
292637
|
try {
|
|
292326
292638
|
await execAsync(
|
|
292327
292639
|
`curl -sL "https://raw.githubusercontent.com/robit-man/personaplex/main/personaplex-setup/moshi/moshi/server.py" -o "${serverDest}"`,
|
|
292328
292640
|
{ timeout: 3e4 }
|
|
292329
292641
|
);
|
|
292330
|
-
if (
|
|
292642
|
+
if (readFileSync45(serverDest, "utf8").includes("hybrid_agent")) {
|
|
292331
292643
|
log22("server.py patched with hybrid intercept + REST APIs.");
|
|
292332
292644
|
}
|
|
292333
292645
|
} catch {
|
|
@@ -292390,7 +292702,7 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292390
292702
|
await execAsync(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('${nf4.repo}', '${nf4.file}', token=False)"`, {
|
|
292391
292703
|
timeout: 6e5
|
|
292392
292704
|
});
|
|
292393
|
-
writeFileSync29(
|
|
292705
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "weight_tier"), "nf4");
|
|
292394
292706
|
log22(`Downloaded INT4 weights instead (${nf4.sizeGB}GB, public).`);
|
|
292395
292707
|
} catch {
|
|
292396
292708
|
log22("Weight download failed.");
|
|
@@ -292402,8 +292714,8 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292402
292714
|
log22("Weights will download on first server launch.");
|
|
292403
292715
|
}
|
|
292404
292716
|
}
|
|
292405
|
-
writeFileSync29(
|
|
292406
|
-
writeFileSync29(
|
|
292717
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "weight_tier"), tier);
|
|
292718
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
|
|
292407
292719
|
log22(`PersonaPlex installed (${tier} tier). Use /call to start voice session.`);
|
|
292408
292720
|
return true;
|
|
292409
292721
|
}
|
|
@@ -292423,14 +292735,14 @@ async function startPersonaPlexDaemon(onInfo) {
|
|
|
292423
292735
|
return null;
|
|
292424
292736
|
}
|
|
292425
292737
|
mkdirSync32(PERSONAPLEX_DIR, { recursive: true });
|
|
292426
|
-
const venvPython2 = process.platform === "win32" ?
|
|
292427
|
-
const sslDir =
|
|
292738
|
+
const venvPython2 = process.platform === "win32" ? join75(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join75(PERSONAPLEX_DIR, "venv", "bin", "python3");
|
|
292739
|
+
const sslDir = join75(PERSONAPLEX_DIR, "ssl");
|
|
292428
292740
|
mkdirSync32(sslDir, { recursive: true });
|
|
292429
292741
|
const tier = getWeightTier();
|
|
292430
292742
|
const repoInfo = WEIGHT_REPOS[tier];
|
|
292431
292743
|
const extraArgs = [];
|
|
292432
292744
|
if (tier !== "original") {
|
|
292433
|
-
const cachedBf16 =
|
|
292745
|
+
const cachedBf16 = join75(PERSONAPLEX_DIR, "model-bf16-cache.safetensors");
|
|
292434
292746
|
if (tier === "nf4-distilled") {
|
|
292435
292747
|
log22(`Weight tier: ${tier} — distilled NF4 (90% token match, ${repoInfo.sizeGB}GB)...`);
|
|
292436
292748
|
try {
|
|
@@ -292438,8 +292750,8 @@ async function startPersonaPlexDaemon(onInfo) {
|
|
|
292438
292750
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`,
|
|
292439
292751
|
{ encoding: "utf8", timeout: 6e4, stdio: "pipe" }
|
|
292440
292752
|
).trim();
|
|
292441
|
-
if (
|
|
292442
|
-
if (!
|
|
292753
|
+
if (existsSync58(weightPath)) {
|
|
292754
|
+
if (!existsSync58(cachedBf16)) {
|
|
292443
292755
|
log22("Converting .pt checkpoint to safetensors (one-time)...");
|
|
292444
292756
|
execSync47(
|
|
292445
292757
|
`"${venvPython2}" -c "
|
|
@@ -292452,7 +292764,7 @@ print('Converted')
|
|
|
292452
292764
|
{ timeout: 18e4, stdio: "pipe" }
|
|
292453
292765
|
);
|
|
292454
292766
|
}
|
|
292455
|
-
if (
|
|
292767
|
+
if (existsSync58(cachedBf16)) {
|
|
292456
292768
|
extraArgs.push("--moshi-weight", cachedBf16);
|
|
292457
292769
|
log22(`Using distilled weights: ${(statSync17(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
|
|
292458
292770
|
} else {
|
|
@@ -292464,12 +292776,12 @@ print('Converted')
|
|
|
292464
292776
|
}
|
|
292465
292777
|
} else {
|
|
292466
292778
|
log22(`Weight tier: ${tier} (${repoInfo.sizeGB}GB) — dequantizing to bf16 cache...`);
|
|
292467
|
-
const dequantScript =
|
|
292468
|
-
if (!
|
|
292779
|
+
const dequantScript = join75(PERSONAPLEX_DIR, "dequant-loader.py");
|
|
292780
|
+
if (!existsSync58(dequantScript)) {
|
|
292469
292781
|
const shipped = getShippedVoicesDir();
|
|
292470
292782
|
if (shipped) {
|
|
292471
|
-
const src2 =
|
|
292472
|
-
if (
|
|
292783
|
+
const src2 = join75(shipped, "dequant-loader.py");
|
|
292784
|
+
if (existsSync58(src2)) copyFileSync2(src2, dequantScript);
|
|
292473
292785
|
}
|
|
292474
292786
|
}
|
|
292475
292787
|
try {
|
|
@@ -292477,13 +292789,13 @@ print('Converted')
|
|
|
292477
292789
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`,
|
|
292478
292790
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292479
292791
|
).trim();
|
|
292480
|
-
if (
|
|
292792
|
+
if (existsSync58(dequantScript) && existsSync58(weightPath)) {
|
|
292481
292793
|
try {
|
|
292482
292794
|
execSync47(
|
|
292483
292795
|
`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`,
|
|
292484
292796
|
{ timeout: 3e5, stdio: "pipe" }
|
|
292485
292797
|
);
|
|
292486
|
-
if (
|
|
292798
|
+
if (existsSync58(cachedBf16)) {
|
|
292487
292799
|
extraArgs.push("--moshi-weight", cachedBf16);
|
|
292488
292800
|
log22(`Using dequantized cache: ${(statSync17(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
|
|
292489
292801
|
}
|
|
@@ -292496,7 +292808,7 @@ print('Converted')
|
|
|
292496
292808
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`,
|
|
292497
292809
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292498
292810
|
).trim();
|
|
292499
|
-
if (
|
|
292811
|
+
if (existsSync58(mimiPath)) extraArgs.push("--mimi-weight", mimiPath);
|
|
292500
292812
|
} catch {
|
|
292501
292813
|
}
|
|
292502
292814
|
try {
|
|
@@ -292504,7 +292816,7 @@ print('Converted')
|
|
|
292504
292816
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`,
|
|
292505
292817
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292506
292818
|
).trim();
|
|
292507
|
-
if (
|
|
292819
|
+
if (existsSync58(tokPath)) extraArgs.push("--tokenizer", tokPath);
|
|
292508
292820
|
} catch {
|
|
292509
292821
|
}
|
|
292510
292822
|
} catch {
|
|
@@ -292517,7 +292829,7 @@ print('Converted')
|
|
|
292517
292829
|
let ollamaModel = process.env["HYBRID_LLM_MODEL"] || "";
|
|
292518
292830
|
if (!ollamaModel) {
|
|
292519
292831
|
try {
|
|
292520
|
-
const oaConfig = JSON.parse(
|
|
292832
|
+
const oaConfig = JSON.parse(readFileSync45(join75(homedir25(), ".open-agents", "config.json"), "utf8"));
|
|
292521
292833
|
if (oaConfig.model) ollamaModel = oaConfig.model;
|
|
292522
292834
|
} catch {
|
|
292523
292835
|
}
|
|
@@ -292616,8 +292928,8 @@ print('Converted')
|
|
|
292616
292928
|
return null;
|
|
292617
292929
|
}
|
|
292618
292930
|
function stopPersonaPlex() {
|
|
292619
|
-
if (!
|
|
292620
|
-
const pid = parseInt(
|
|
292931
|
+
if (!existsSync58(PID_FILE)) return;
|
|
292932
|
+
const pid = parseInt(readFileSync45(PID_FILE, "utf8").trim(), 10);
|
|
292621
292933
|
if (isNaN(pid) || pid <= 0) return;
|
|
292622
292934
|
try {
|
|
292623
292935
|
if (process.platform === "win32") {
|
|
@@ -292653,12 +292965,12 @@ function listPersonaPlexVoices() {
|
|
|
292653
292965
|
for (const name10 of builtins) {
|
|
292654
292966
|
voices.push({ name: name10, type: "builtin", path: `${name10}.pt` });
|
|
292655
292967
|
}
|
|
292656
|
-
if (
|
|
292968
|
+
if (existsSync58(CUSTOM_VOICES_DIR)) {
|
|
292657
292969
|
try {
|
|
292658
292970
|
for (const f2 of readdirSync15(CUSTOM_VOICES_DIR)) {
|
|
292659
292971
|
if (f2.endsWith(".pt")) {
|
|
292660
292972
|
const name10 = f2.replace(/\.pt$/, "");
|
|
292661
|
-
voices.push({ name: name10, type: "custom", path:
|
|
292973
|
+
voices.push({ name: name10, type: "custom", path: join75(CUSTOM_VOICES_DIR, f2) });
|
|
292662
292974
|
}
|
|
292663
292975
|
}
|
|
292664
292976
|
} catch {
|
|
@@ -292673,19 +292985,19 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292673
292985
|
log22("PersonaPlex not installed. Run /voice personaplex first.");
|
|
292674
292986
|
return null;
|
|
292675
292987
|
}
|
|
292676
|
-
if (!
|
|
292988
|
+
if (!existsSync58(inputWav)) {
|
|
292677
292989
|
log22(`Input WAV not found: ${inputWav}`);
|
|
292678
292990
|
return null;
|
|
292679
292991
|
}
|
|
292680
292992
|
mkdirSync32(CUSTOM_VOICES_DIR, { recursive: true });
|
|
292681
|
-
const outputPt =
|
|
292682
|
-
if (
|
|
292993
|
+
const outputPt = join75(CUSTOM_VOICES_DIR, `${voiceName}.pt`);
|
|
292994
|
+
if (existsSync58(outputPt)) {
|
|
292683
292995
|
log22(`Voice "${voiceName}" already exists. Delete ${outputPt} to re-clone.`);
|
|
292684
292996
|
return outputPt;
|
|
292685
292997
|
}
|
|
292686
|
-
const venvPython2 = process.platform === "win32" ?
|
|
292687
|
-
const cloneScript =
|
|
292688
|
-
if (!
|
|
292998
|
+
const venvPython2 = process.platform === "win32" ? join75(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join75(PERSONAPLEX_DIR, "venv", "bin", "python3");
|
|
292999
|
+
const cloneScript = join75(PERSONAPLEX_DIR, "clone-voice.py");
|
|
293000
|
+
if (!existsSync58(cloneScript)) {
|
|
292689
293001
|
log22("clone-voice.py not found. Reinstall PersonaPlex.");
|
|
292690
293002
|
return null;
|
|
292691
293003
|
}
|
|
@@ -292717,7 +293029,7 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292717
293029
|
output += d2.toString();
|
|
292718
293030
|
});
|
|
292719
293031
|
child.on("close", (code8) => {
|
|
292720
|
-
if (code8 === 0 &&
|
|
293032
|
+
if (code8 === 0 && existsSync58(outputPt)) {
|
|
292721
293033
|
log22(`Voice "${voiceName}" cloned successfully.`);
|
|
292722
293034
|
resolve39(outputPt);
|
|
292723
293035
|
} else {
|
|
@@ -292729,19 +293041,19 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292729
293041
|
}
|
|
292730
293042
|
function getShippedVoicesDir() {
|
|
292731
293043
|
const candidates = [
|
|
292732
|
-
|
|
293044
|
+
join75(PERSONAPLEX_DIR, "shipped_voices"),
|
|
292733
293045
|
// cached copy
|
|
292734
|
-
|
|
293046
|
+
join75(process.cwd(), "voices", "personaplex")
|
|
292735
293047
|
// repo root
|
|
292736
293048
|
];
|
|
292737
293049
|
try {
|
|
292738
293050
|
const modDir = dirname21(fileURLToPath12(import.meta.url));
|
|
292739
|
-
candidates.push(
|
|
292740
|
-
candidates.push(
|
|
293051
|
+
candidates.push(join75(modDir, "..", "..", "..", "voices", "personaplex"));
|
|
293052
|
+
candidates.push(join75(modDir, "..", "..", "..", "..", "voices", "personaplex"));
|
|
292741
293053
|
} catch {
|
|
292742
293054
|
}
|
|
292743
293055
|
for (const dir of candidates) {
|
|
292744
|
-
if (
|
|
293056
|
+
if (existsSync58(dir)) {
|
|
292745
293057
|
try {
|
|
292746
293058
|
const files = readdirSync15(dir);
|
|
292747
293059
|
if (files.some((f2) => f2.endsWith(".pt"))) return dir;
|
|
@@ -292762,14 +293074,14 @@ function provisionShippedVoices(onInfo) {
|
|
|
292762
293074
|
try {
|
|
292763
293075
|
for (const f2 of readdirSync15(shippedDir)) {
|
|
292764
293076
|
if (!f2.endsWith(".pt")) continue;
|
|
292765
|
-
const customDst =
|
|
292766
|
-
if (!
|
|
292767
|
-
copyFileSync2(
|
|
293077
|
+
const customDst = join75(CUSTOM_VOICES_DIR, f2);
|
|
293078
|
+
if (!existsSync58(customDst)) {
|
|
293079
|
+
copyFileSync2(join75(shippedDir, f2), customDst);
|
|
292768
293080
|
}
|
|
292769
293081
|
if (hfVoicesDir) {
|
|
292770
|
-
const hfDst =
|
|
292771
|
-
if (!
|
|
292772
|
-
copyFileSync2(
|
|
293082
|
+
const hfDst = join75(hfVoicesDir, f2);
|
|
293083
|
+
if (!existsSync58(hfDst)) {
|
|
293084
|
+
copyFileSync2(join75(shippedDir, f2), hfDst);
|
|
292773
293085
|
log22(`Deployed voice: ${f2.replace(".pt", "")}`);
|
|
292774
293086
|
deployed++;
|
|
292775
293087
|
}
|
|
@@ -292777,9 +293089,9 @@ function provisionShippedVoices(onInfo) {
|
|
|
292777
293089
|
}
|
|
292778
293090
|
} catch {
|
|
292779
293091
|
}
|
|
292780
|
-
const shippedScript =
|
|
292781
|
-
const targetScript =
|
|
292782
|
-
if (
|
|
293092
|
+
const shippedScript = join75(shippedDir, "clone-voice.py");
|
|
293093
|
+
const targetScript = join75(PERSONAPLEX_DIR, "clone-voice.py");
|
|
293094
|
+
if (existsSync58(shippedScript) && !existsSync58(targetScript)) {
|
|
292783
293095
|
try {
|
|
292784
293096
|
copyFileSync2(shippedScript, targetScript);
|
|
292785
293097
|
} catch {
|
|
@@ -292788,14 +293100,14 @@ function provisionShippedVoices(onInfo) {
|
|
|
292788
293100
|
return deployed;
|
|
292789
293101
|
}
|
|
292790
293102
|
function getHFVoicesDir() {
|
|
292791
|
-
const hfBase =
|
|
292792
|
-
if (!
|
|
293103
|
+
const hfBase = join75(homedir25(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
|
|
293104
|
+
if (!existsSync58(hfBase)) return null;
|
|
292793
293105
|
try {
|
|
292794
|
-
const snapshots =
|
|
292795
|
-
if (!
|
|
293106
|
+
const snapshots = join75(hfBase, "snapshots");
|
|
293107
|
+
if (!existsSync58(snapshots)) return null;
|
|
292796
293108
|
for (const snap of readdirSync15(snapshots)) {
|
|
292797
|
-
const voicesDir =
|
|
292798
|
-
if (
|
|
293109
|
+
const voicesDir = join75(snapshots, snap, "voices");
|
|
293110
|
+
if (existsSync58(voicesDir)) return voicesDir;
|
|
292799
293111
|
}
|
|
292800
293112
|
} catch {
|
|
292801
293113
|
}
|
|
@@ -292804,19 +293116,19 @@ function getHFVoicesDir() {
|
|
|
292804
293116
|
function patchFrontendVoiceList(onInfo) {
|
|
292805
293117
|
const log22 = onInfo ?? (() => {
|
|
292806
293118
|
});
|
|
292807
|
-
const hfBase =
|
|
292808
|
-
if (!
|
|
293119
|
+
const hfBase = join75(homedir25(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
|
|
293120
|
+
if (!existsSync58(hfBase)) return;
|
|
292809
293121
|
try {
|
|
292810
|
-
const snapshots =
|
|
293122
|
+
const snapshots = join75(hfBase, "snapshots");
|
|
292811
293123
|
for (const snap of readdirSync15(snapshots)) {
|
|
292812
|
-
const distDir =
|
|
292813
|
-
if (!
|
|
293124
|
+
const distDir = join75(snapshots, snap, "dist", "assets");
|
|
293125
|
+
if (!existsSync58(distDir)) continue;
|
|
292814
293126
|
for (const f2 of readdirSync15(distDir)) {
|
|
292815
293127
|
if (!f2.startsWith("index-") || !f2.endsWith(".js")) continue;
|
|
292816
|
-
const jsPath =
|
|
292817
|
-
let js =
|
|
293128
|
+
const jsPath = join75(distDir, f2);
|
|
293129
|
+
let js = readFileSync45(jsPath, "utf8");
|
|
292818
293130
|
const customVoices = [];
|
|
292819
|
-
if (
|
|
293131
|
+
if (existsSync58(CUSTOM_VOICES_DIR)) {
|
|
292820
293132
|
for (const vf of readdirSync15(CUSTOM_VOICES_DIR)) {
|
|
292821
293133
|
if (vf.endsWith(".pt")) {
|
|
292822
293134
|
const name10 = vf.replace(".pt", "");
|
|
@@ -292882,11 +293194,11 @@ var init_personaplex = __esm({
|
|
|
292882
293194
|
nf4: { repo: "cudabenchmarktest/personaplex-7b-nf4", file: "model-nf4.safetensors", sizeGB: 4.1, needsToken: false },
|
|
292883
293195
|
"nf4-distilled": { repo: "cudabenchmarktest/personaplex-7b-nf4-distilled", file: "student_best.pt", sizeGB: 16.7, needsToken: false }
|
|
292884
293196
|
};
|
|
292885
|
-
PERSONAPLEX_DIR =
|
|
292886
|
-
PID_FILE =
|
|
292887
|
-
PORT_FILE =
|
|
292888
|
-
LOG_FILE =
|
|
292889
|
-
CUSTOM_VOICES_DIR =
|
|
293197
|
+
PERSONAPLEX_DIR = join75(homedir25(), ".open-agents", "voice", "personaplex");
|
|
293198
|
+
PID_FILE = join75(PERSONAPLEX_DIR, "daemon.pid");
|
|
293199
|
+
PORT_FILE = join75(PERSONAPLEX_DIR, "daemon.port");
|
|
293200
|
+
LOG_FILE = join75(PERSONAPLEX_DIR, "daemon.log");
|
|
293201
|
+
CUSTOM_VOICES_DIR = join75(PERSONAPLEX_DIR, "custom_voices");
|
|
292890
293202
|
}
|
|
292891
293203
|
});
|
|
292892
293204
|
|
|
@@ -292927,9 +293239,9 @@ __export(setup_exports, {
|
|
|
292927
293239
|
import * as readline from "node:readline";
|
|
292928
293240
|
import { execSync as execSync48, spawn as spawn22, exec as exec4 } from "node:child_process";
|
|
292929
293241
|
import { promisify as promisify7 } from "node:util";
|
|
292930
|
-
import { existsSync as
|
|
292931
|
-
import { join as
|
|
292932
|
-
import { homedir as
|
|
293242
|
+
import { existsSync as existsSync59, writeFileSync as writeFileSync30, readFileSync as readFileSync46, appendFileSync as appendFileSync2, mkdirSync as mkdirSync33 } from "node:fs";
|
|
293243
|
+
import { join as join76 } from "node:path";
|
|
293244
|
+
import { homedir as homedir26, platform as platform3 } from "node:os";
|
|
292933
293245
|
async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
|
|
292934
293246
|
if (_toolSupportCache.has(modelName)) return _toolSupportCache.get(modelName);
|
|
292935
293247
|
try {
|
|
@@ -293321,7 +293633,7 @@ async function installOllamaMac(_rl) {
|
|
|
293321
293633
|
);
|
|
293322
293634
|
if (!hasCmd("brew")) {
|
|
293323
293635
|
try {
|
|
293324
|
-
const brewPrefix =
|
|
293636
|
+
const brewPrefix = existsSync59("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
293325
293637
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
293326
293638
|
} catch {
|
|
293327
293639
|
}
|
|
@@ -294106,9 +294418,9 @@ async function doSetup(config, rl) {
|
|
|
294106
294418
|
`PARAMETER num_predict ${numPredict}`,
|
|
294107
294419
|
`PARAMETER stop "<|endoftext|>"`
|
|
294108
294420
|
].join("\n");
|
|
294109
|
-
const modelDir2 =
|
|
294421
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294110
294422
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294111
|
-
const modelfilePath =
|
|
294423
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294112
294424
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294113
294425
|
process.stdout.write(` ${c3.dim("Creating model...")} `);
|
|
294114
294426
|
execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
@@ -294154,7 +294466,7 @@ async function isModelAvailable(config) {
|
|
|
294154
294466
|
}
|
|
294155
294467
|
function isFirstRun() {
|
|
294156
294468
|
try {
|
|
294157
|
-
return !
|
|
294469
|
+
return !existsSync59(join76(homedir26(), ".open-agents", "config.json"));
|
|
294158
294470
|
} catch {
|
|
294159
294471
|
return true;
|
|
294160
294472
|
}
|
|
@@ -294202,7 +294514,7 @@ function detectPkgManager() {
|
|
|
294202
294514
|
return null;
|
|
294203
294515
|
}
|
|
294204
294516
|
function getVenvDir() {
|
|
294205
|
-
return
|
|
294517
|
+
return join76(homedir26(), ".open-agents", "venv");
|
|
294206
294518
|
}
|
|
294207
294519
|
function hasVenvModule() {
|
|
294208
294520
|
try {
|
|
@@ -294215,10 +294527,10 @@ function hasVenvModule() {
|
|
|
294215
294527
|
function ensureVenv(log22) {
|
|
294216
294528
|
const venvDir = getVenvDir();
|
|
294217
294529
|
const isWin2 = process.platform === "win32";
|
|
294218
|
-
const pipPath = isWin2 ?
|
|
294219
|
-
const venvPyPath = isWin2 ?
|
|
294530
|
+
const pipPath = isWin2 ? join76(venvDir, "Scripts", "pip.exe") : join76(venvDir, "bin", "pip");
|
|
294531
|
+
const venvPyPath = isWin2 ? join76(venvDir, "Scripts", "python.exe") : join76(venvDir, "bin", "python3");
|
|
294220
294532
|
const pythonCmd = isWin2 ? "python" : "python3";
|
|
294221
|
-
if (
|
|
294533
|
+
if (existsSync59(pipPath)) {
|
|
294222
294534
|
try {
|
|
294223
294535
|
execSync48(`"${venvPyPath}" -m pip --version`, { stdio: "pipe", timeout: 1e4 });
|
|
294224
294536
|
return venvDir;
|
|
@@ -294249,7 +294561,7 @@ function ensureVenv(log22) {
|
|
|
294249
294561
|
return null;
|
|
294250
294562
|
}
|
|
294251
294563
|
try {
|
|
294252
|
-
mkdirSync33(
|
|
294564
|
+
mkdirSync33(join76(homedir26(), ".open-agents"), { recursive: true });
|
|
294253
294565
|
const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
|
|
294254
294566
|
execSync48(`${pyCmd} -m venv --clear "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
294255
294567
|
try {
|
|
@@ -294358,12 +294670,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294358
294670
|
];
|
|
294359
294671
|
{
|
|
294360
294672
|
const pm2 = detectPkgManager();
|
|
294361
|
-
const _visionMarkerDir =
|
|
294362
|
-
const _visionMarkerFile =
|
|
294673
|
+
const _visionMarkerDir = join76(homedir26(), ".open-agents");
|
|
294674
|
+
const _visionMarkerFile = join76(_visionMarkerDir, "vision-deps-installed.json");
|
|
294363
294675
|
let _visionPreviouslyInstalled = /* @__PURE__ */ new Set();
|
|
294364
294676
|
try {
|
|
294365
|
-
if (
|
|
294366
|
-
const _vm = JSON.parse(
|
|
294677
|
+
if (existsSync59(_visionMarkerFile)) {
|
|
294678
|
+
const _vm = JSON.parse(readFileSync46(_visionMarkerFile, "utf8"));
|
|
294367
294679
|
_visionPreviouslyInstalled = new Set(_vm.installed || []);
|
|
294368
294680
|
}
|
|
294369
294681
|
} catch {
|
|
@@ -294529,15 +294841,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294529
294841
|
}
|
|
294530
294842
|
const venvDir = getVenvDir();
|
|
294531
294843
|
const isWin2 = process.platform === "win32";
|
|
294532
|
-
const venvBin =
|
|
294533
|
-
const venvMoondream =
|
|
294844
|
+
const venvBin = join76(venvDir, isWin2 ? "Scripts" : "bin");
|
|
294845
|
+
const venvMoondream = join76(venvBin, isWin2 ? "moondream-station.exe" : "moondream-station");
|
|
294534
294846
|
const venv = ensureVenv(log22);
|
|
294535
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
294536
|
-
const venvPip2 =
|
|
294847
|
+
if (venv && !hasCmd("moondream-station") && !existsSync59(venvMoondream)) {
|
|
294848
|
+
const venvPip2 = join76(venvBin, "pip");
|
|
294537
294849
|
log22("Installing moondream-station in ~/.open-agents/venv...");
|
|
294538
294850
|
try {
|
|
294539
294851
|
execSync48(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
294540
|
-
if (
|
|
294852
|
+
if (existsSync59(venvMoondream)) {
|
|
294541
294853
|
log22("moondream-station installed successfully.");
|
|
294542
294854
|
} else {
|
|
294543
294855
|
try {
|
|
@@ -294554,8 +294866,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294554
294866
|
}
|
|
294555
294867
|
}
|
|
294556
294868
|
if (venv) {
|
|
294557
|
-
const venvPython2 =
|
|
294558
|
-
const venvPip2 =
|
|
294869
|
+
const venvPython2 = join76(venvBin, isWin2 ? "python.exe" : "python");
|
|
294870
|
+
const venvPip2 = join76(venvBin, isWin2 ? "pip.exe" : "pip");
|
|
294559
294871
|
let ocrStackInstalled = false;
|
|
294560
294872
|
try {
|
|
294561
294873
|
execSync48(
|
|
@@ -294611,11 +294923,11 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
294611
294923
|
const cfArch = archMap[arch2] ?? "amd64";
|
|
294612
294924
|
try {
|
|
294613
294925
|
execSync48(
|
|
294614
|
-
`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${
|
|
294926
|
+
`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir26()}/.local/bin" && mv /tmp/cloudflared "${homedir26()}/.local/bin/cloudflared"`,
|
|
294615
294927
|
{ stdio: "pipe", timeout: 6e4 }
|
|
294616
294928
|
);
|
|
294617
|
-
if (!process.env.PATH?.includes(`${
|
|
294618
|
-
process.env.PATH = `${
|
|
294929
|
+
if (!process.env.PATH?.includes(`${homedir26()}/.local/bin`)) {
|
|
294930
|
+
process.env.PATH = `${homedir26()}/.local/bin:${process.env.PATH}`;
|
|
294619
294931
|
}
|
|
294620
294932
|
if (hasCmd("cloudflared")) {
|
|
294621
294933
|
log22("cloudflared installed.");
|
|
@@ -294712,9 +295024,9 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
|
|
|
294712
295024
|
`PARAMETER num_predict ${numPredict}`,
|
|
294713
295025
|
`PARAMETER stop "<|endoftext|>"`
|
|
294714
295026
|
].join("\n");
|
|
294715
|
-
const modelDir2 =
|
|
295027
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294716
295028
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294717
|
-
const modelfilePath =
|
|
295029
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294718
295030
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294719
295031
|
execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
294720
295032
|
stdio: "pipe",
|
|
@@ -294737,9 +295049,9 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
|
|
|
294737
295049
|
`PARAMETER num_predict ${numPredict}`,
|
|
294738
295050
|
`PARAMETER stop "<|endoftext|>"`
|
|
294739
295051
|
].join("\n");
|
|
294740
|
-
const modelDir2 =
|
|
295052
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294741
295053
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294742
|
-
const modelfilePath =
|
|
295054
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294743
295055
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294744
295056
|
await execAsync2(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
294745
295057
|
timeout: 12e4
|
|
@@ -294813,8 +295125,8 @@ async function ensureNeovim() {
|
|
|
294813
295125
|
const platform6 = process.platform;
|
|
294814
295126
|
const arch2 = process.arch;
|
|
294815
295127
|
if (platform6 === "linux") {
|
|
294816
|
-
const binDir =
|
|
294817
|
-
const nvimDest =
|
|
295128
|
+
const binDir = join76(homedir26(), ".local", "bin");
|
|
295129
|
+
const nvimDest = join76(binDir, "nvim");
|
|
294818
295130
|
try {
|
|
294819
295131
|
mkdirSync33(binDir, { recursive: true });
|
|
294820
295132
|
} catch {
|
|
@@ -294885,9 +295197,9 @@ async function ensureNeovim() {
|
|
|
294885
295197
|
}
|
|
294886
295198
|
function ensurePathInShellRc(binDir) {
|
|
294887
295199
|
const shell = process.env.SHELL ?? "";
|
|
294888
|
-
const rcFile = shell.includes("zsh") ?
|
|
295200
|
+
const rcFile = shell.includes("zsh") ? join76(homedir26(), ".zshrc") : join76(homedir26(), ".bashrc");
|
|
294889
295201
|
try {
|
|
294890
|
-
const rcContent =
|
|
295202
|
+
const rcContent = existsSync59(rcFile) ? readFileSync46(rcFile, "utf8") : "";
|
|
294891
295203
|
if (rcContent.includes(binDir)) return;
|
|
294892
295204
|
const exportLine = `
|
|
294893
295205
|
export PATH="${binDir}:$PATH" # Added by open-agents for nvim
|
|
@@ -294924,7 +295236,7 @@ var init_setup = __esm({
|
|
|
294924
295236
|
});
|
|
294925
295237
|
|
|
294926
295238
|
// packages/cli/src/tui/drop-panel.ts
|
|
294927
|
-
import { existsSync as
|
|
295239
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
294928
295240
|
import { extname as extname10, resolve as resolve31 } from "node:path";
|
|
294929
295241
|
function ansi4(code8, text) {
|
|
294930
295242
|
return isTTY4 ? `\x1B[${code8}m${text}\x1B[0m` : text;
|
|
@@ -295045,7 +295357,7 @@ function showDropPanel(opts) {
|
|
|
295045
295357
|
filePath = decodeURIComponent(filePath.slice(7));
|
|
295046
295358
|
}
|
|
295047
295359
|
filePath = resolve31(filePath);
|
|
295048
|
-
if (!
|
|
295360
|
+
if (!existsSync60(filePath)) {
|
|
295049
295361
|
errorMsg = `File not found: ${filePath}`;
|
|
295050
295362
|
render2();
|
|
295051
295363
|
return;
|
|
@@ -295117,9 +295429,9 @@ var init_drop_panel = __esm({
|
|
|
295117
295429
|
});
|
|
295118
295430
|
|
|
295119
295431
|
// packages/cli/src/tui/neovim-mode.ts
|
|
295120
|
-
import { existsSync as
|
|
295432
|
+
import { existsSync as existsSync61, unlinkSync as unlinkSync15 } from "node:fs";
|
|
295121
295433
|
import { tmpdir as tmpdir18 } from "node:os";
|
|
295122
|
-
import { join as
|
|
295434
|
+
import { join as join77 } from "node:path";
|
|
295123
295435
|
import { execSync as execSync49 } from "node:child_process";
|
|
295124
295436
|
function isNeovimActive() {
|
|
295125
295437
|
return _state !== null && !_state.cleanedUp;
|
|
@@ -295165,9 +295477,9 @@ async function startNeovimMode(opts) {
|
|
|
295165
295477
|
);
|
|
295166
295478
|
} catch {
|
|
295167
295479
|
}
|
|
295168
|
-
const socketPath =
|
|
295480
|
+
const socketPath = join77(tmpdir18(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
|
|
295169
295481
|
try {
|
|
295170
|
-
if (
|
|
295482
|
+
if (existsSync61(socketPath)) unlinkSync15(socketPath);
|
|
295171
295483
|
} catch {
|
|
295172
295484
|
}
|
|
295173
295485
|
const ptyCols = opts.cols;
|
|
@@ -295414,12 +295726,12 @@ function resizeNeovim(cols, contentRows) {
|
|
|
295414
295726
|
}
|
|
295415
295727
|
async function connectRPC(state, neovimPkg, cols) {
|
|
295416
295728
|
let attempts = 0;
|
|
295417
|
-
while (!
|
|
295729
|
+
while (!existsSync61(state.socketPath) && attempts < 30) {
|
|
295418
295730
|
await new Promise((r2) => setTimeout(r2, 200));
|
|
295419
295731
|
attempts++;
|
|
295420
295732
|
if (state.cleanedUp) return;
|
|
295421
295733
|
}
|
|
295422
|
-
if (!
|
|
295734
|
+
if (!existsSync61(state.socketPath)) return;
|
|
295423
295735
|
const nvim = neovimPkg.attach({ socket: state.socketPath });
|
|
295424
295736
|
state.nvim = nvim;
|
|
295425
295737
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
@@ -295556,7 +295868,7 @@ function doCleanup(state) {
|
|
|
295556
295868
|
state.pty = null;
|
|
295557
295869
|
}
|
|
295558
295870
|
try {
|
|
295559
|
-
if (
|
|
295871
|
+
if (existsSync61(state.socketPath)) unlinkSync15(state.socketPath);
|
|
295560
295872
|
} catch {
|
|
295561
295873
|
}
|
|
295562
295874
|
if (state.stdinHandler) {
|
|
@@ -295626,9 +295938,9 @@ __export(daemon_exports, {
|
|
|
295626
295938
|
stopDaemon: () => stopDaemon
|
|
295627
295939
|
});
|
|
295628
295940
|
import { spawn as spawn23 } from "node:child_process";
|
|
295629
|
-
import { existsSync as
|
|
295630
|
-
import { join as
|
|
295631
|
-
import { homedir as
|
|
295941
|
+
import { existsSync as existsSync62, readFileSync as readFileSync47, writeFileSync as writeFileSync31, mkdirSync as mkdirSync34, unlinkSync as unlinkSync16 } from "node:fs";
|
|
295942
|
+
import { join as join78 } from "node:path";
|
|
295943
|
+
import { homedir as homedir27 } from "node:os";
|
|
295632
295944
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
295633
295945
|
import { dirname as dirname22 } from "node:path";
|
|
295634
295946
|
function getDaemonPort() {
|
|
@@ -295652,9 +295964,9 @@ async function isDaemonRunning(port) {
|
|
|
295652
295964
|
}
|
|
295653
295965
|
}
|
|
295654
295966
|
function getDaemonPid() {
|
|
295655
|
-
if (!
|
|
295967
|
+
if (!existsSync62(PID_FILE2)) return null;
|
|
295656
295968
|
try {
|
|
295657
|
-
const pid = parseInt(
|
|
295969
|
+
const pid = parseInt(readFileSync47(PID_FILE2, "utf8").trim(), 10);
|
|
295658
295970
|
if (!pid || pid <= 0) return null;
|
|
295659
295971
|
process.kill(pid, 0);
|
|
295660
295972
|
return pid;
|
|
@@ -295680,8 +295992,8 @@ async function startDaemon() {
|
|
|
295680
295992
|
}
|
|
295681
295993
|
if (!oaScript) {
|
|
295682
295994
|
const thisDir = dirname22(fileURLToPath13(import.meta.url));
|
|
295683
|
-
const indexJs =
|
|
295684
|
-
if (
|
|
295995
|
+
const indexJs = join78(thisDir, "index.js");
|
|
295996
|
+
if (existsSync62(indexJs)) oaScript = indexJs;
|
|
295685
295997
|
}
|
|
295686
295998
|
if (!oaScript) return null;
|
|
295687
295999
|
try {
|
|
@@ -295779,8 +296091,8 @@ var OA_DIR2, PID_FILE2, DEFAULT_PORT2;
|
|
|
295779
296091
|
var init_daemon = __esm({
|
|
295780
296092
|
"packages/cli/src/daemon.ts"() {
|
|
295781
296093
|
"use strict";
|
|
295782
|
-
OA_DIR2 =
|
|
295783
|
-
PID_FILE2 =
|
|
296094
|
+
OA_DIR2 = join78(homedir27(), ".open-agents");
|
|
296095
|
+
PID_FILE2 = join78(OA_DIR2, "daemon.pid");
|
|
295784
296096
|
DEFAULT_PORT2 = 11435;
|
|
295785
296097
|
}
|
|
295786
296098
|
});
|
|
@@ -296165,8 +296477,8 @@ __export(sponsor_wizard_exports, {
|
|
|
296165
296477
|
saveSponsorConfig: () => saveSponsorConfig,
|
|
296166
296478
|
showSponsorDashboard: () => showSponsorDashboard
|
|
296167
296479
|
});
|
|
296168
|
-
import { existsSync as
|
|
296169
|
-
import { join as
|
|
296480
|
+
import { existsSync as existsSync63, readFileSync as readFileSync48, writeFileSync as writeFileSync32, mkdirSync as mkdirSync35 } from "node:fs";
|
|
296481
|
+
import { join as join79 } from "node:path";
|
|
296170
296482
|
function colorPreview(code8) {
|
|
296171
296483
|
return `\x1B[38;5;${code8}m████\x1B[0m (${code8})`;
|
|
296172
296484
|
}
|
|
@@ -296179,16 +296491,16 @@ function gradientPreview(start2, end) {
|
|
|
296179
296491
|
return s2;
|
|
296180
296492
|
}
|
|
296181
296493
|
function sponsorDir(projectDir) {
|
|
296182
|
-
return
|
|
296494
|
+
return join79(projectDir, ".oa", "sponsor");
|
|
296183
296495
|
}
|
|
296184
296496
|
function configPath(projectDir) {
|
|
296185
|
-
return
|
|
296497
|
+
return join79(sponsorDir(projectDir), "config.json");
|
|
296186
296498
|
}
|
|
296187
296499
|
function loadSponsorConfig(projectDir) {
|
|
296188
296500
|
const p2 = configPath(projectDir);
|
|
296189
|
-
if (!
|
|
296501
|
+
if (!existsSync63(p2)) return null;
|
|
296190
296502
|
try {
|
|
296191
|
-
return JSON.parse(
|
|
296503
|
+
return JSON.parse(readFileSync48(p2, "utf8"));
|
|
296192
296504
|
} catch {
|
|
296193
296505
|
return null;
|
|
296194
296506
|
}
|
|
@@ -297077,9 +297389,9 @@ __export(voice_exports, {
|
|
|
297077
297389
|
registerCustomOnnxModel: () => registerCustomOnnxModel,
|
|
297078
297390
|
resetNarrationContext: () => resetNarrationContext
|
|
297079
297391
|
});
|
|
297080
|
-
import { existsSync as
|
|
297081
|
-
import { join as
|
|
297082
|
-
import { homedir as
|
|
297392
|
+
import { existsSync as existsSync64, mkdirSync as mkdirSync36, writeFileSync as writeFileSync33, readFileSync as readFileSync49, unlinkSync as unlinkSync17, readdirSync as readdirSync16, statSync as statSync18 } from "node:fs";
|
|
297393
|
+
import { join as join80, dirname as dirname23 } from "node:path";
|
|
297394
|
+
import { homedir as homedir28, tmpdir as tmpdir19, platform as platform4 } from "node:os";
|
|
297083
297395
|
import { execSync as execSync50, spawn as nodeSpawn } from "node:child_process";
|
|
297084
297396
|
import { createRequire as createRequire3 } from "node:module";
|
|
297085
297397
|
function sanitizeForTTS(text) {
|
|
@@ -297103,37 +297415,37 @@ function listVoiceModels() {
|
|
|
297103
297415
|
}));
|
|
297104
297416
|
}
|
|
297105
297417
|
function voiceDir() {
|
|
297106
|
-
return
|
|
297418
|
+
return join80(homedir28(), ".open-agents", "voice");
|
|
297107
297419
|
}
|
|
297108
297420
|
function modelsDir() {
|
|
297109
|
-
return
|
|
297421
|
+
return join80(voiceDir(), "models");
|
|
297110
297422
|
}
|
|
297111
297423
|
function modelDir(id) {
|
|
297112
|
-
return
|
|
297424
|
+
return join80(modelsDir(), id);
|
|
297113
297425
|
}
|
|
297114
297426
|
function modelOnnxPath(id) {
|
|
297115
|
-
return
|
|
297427
|
+
return join80(modelDir(id), "model.onnx");
|
|
297116
297428
|
}
|
|
297117
297429
|
function modelConfigPath(id) {
|
|
297118
|
-
return
|
|
297430
|
+
return join80(modelDir(id), "config.json");
|
|
297119
297431
|
}
|
|
297120
297432
|
function luxttsVenvDir() {
|
|
297121
|
-
return
|
|
297433
|
+
return join80(voiceDir(), "luxtts-venv");
|
|
297122
297434
|
}
|
|
297123
297435
|
function luxttsVenvPy() {
|
|
297124
|
-
return platform4() === "win32" ?
|
|
297436
|
+
return platform4() === "win32" ? join80(luxttsVenvDir(), "Scripts", "python.exe") : join80(luxttsVenvDir(), "bin", "python3");
|
|
297125
297437
|
}
|
|
297126
297438
|
function luxttsRepoDir() {
|
|
297127
|
-
return
|
|
297439
|
+
return join80(voiceDir(), "LuxTTS");
|
|
297128
297440
|
}
|
|
297129
297441
|
function luxttsCloneRefsDir() {
|
|
297130
|
-
return
|
|
297442
|
+
return join80(voiceDir(), "clone-refs");
|
|
297131
297443
|
}
|
|
297132
297444
|
function luxttsInferScript() {
|
|
297133
|
-
return
|
|
297445
|
+
return join80(voiceDir(), "luxtts-infer.py");
|
|
297134
297446
|
}
|
|
297135
297447
|
function writeDetectTorchScript(targetPath) {
|
|
297136
|
-
if (
|
|
297448
|
+
if (existsSync64(targetPath)) return;
|
|
297137
297449
|
try {
|
|
297138
297450
|
mkdirSync36(dirname23(targetPath), { recursive: true });
|
|
297139
297451
|
} catch {
|
|
@@ -297958,8 +298270,8 @@ var init_voice = __esm({
|
|
|
297958
298270
|
const refsDir = luxttsCloneRefsDir();
|
|
297959
298271
|
const targets = ["glados", "overwatch"];
|
|
297960
298272
|
for (const modelId of targets) {
|
|
297961
|
-
const refFile =
|
|
297962
|
-
if (
|
|
298273
|
+
const refFile = join80(refsDir, `${modelId}-ref.wav`);
|
|
298274
|
+
if (existsSync64(refFile)) continue;
|
|
297963
298275
|
try {
|
|
297964
298276
|
await this.generateCloneRef(modelId);
|
|
297965
298277
|
const meta = this.loadCloneMeta();
|
|
@@ -298035,22 +298347,22 @@ var init_voice = __esm({
|
|
|
298035
298347
|
}
|
|
298036
298348
|
p2 = p2.replace(/\\ /g, " ");
|
|
298037
298349
|
if (p2.startsWith("~/") || p2 === "~") {
|
|
298038
|
-
p2 =
|
|
298350
|
+
p2 = join80(homedir28(), p2.slice(1));
|
|
298039
298351
|
}
|
|
298040
|
-
if (!
|
|
298352
|
+
if (!existsSync64(p2)) {
|
|
298041
298353
|
return `File not found: ${p2}
|
|
298042
298354
|
(original input: ${audioPath})`;
|
|
298043
298355
|
}
|
|
298044
298356
|
audioPath = p2;
|
|
298045
298357
|
const refsDir = luxttsCloneRefsDir();
|
|
298046
|
-
if (!
|
|
298358
|
+
if (!existsSync64(refsDir)) mkdirSync36(refsDir, { recursive: true });
|
|
298047
298359
|
const ext = audioPath.split(".").pop() || "wav";
|
|
298048
298360
|
const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
298049
298361
|
const ts = Date.now().toString(36);
|
|
298050
298362
|
const destFilename = `clone-${srcName}-${ts}.${ext}`;
|
|
298051
|
-
const destPath =
|
|
298363
|
+
const destPath = join80(refsDir, destFilename);
|
|
298052
298364
|
try {
|
|
298053
|
-
const data =
|
|
298365
|
+
const data = readFileSync49(audioPath);
|
|
298054
298366
|
writeFileSync33(destPath, data);
|
|
298055
298367
|
} catch (err) {
|
|
298056
298368
|
return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
|
|
@@ -298091,8 +298403,8 @@ var init_voice = __esm({
|
|
|
298091
298403
|
return `Failed to synthesize reference audio from ${source.label}.`;
|
|
298092
298404
|
}
|
|
298093
298405
|
const refsDir = luxttsCloneRefsDir();
|
|
298094
|
-
if (!
|
|
298095
|
-
const destPath =
|
|
298406
|
+
if (!existsSync64(refsDir)) mkdirSync36(refsDir, { recursive: true });
|
|
298407
|
+
const destPath = join80(refsDir, `${sourceModelId}-ref.wav`);
|
|
298096
298408
|
const sampleRate = this.config?.audio?.sample_rate ?? 22050;
|
|
298097
298409
|
this.writeWav(audioData, sampleRate, destPath);
|
|
298098
298410
|
this.luxttsCloneRef = destPath;
|
|
@@ -298108,20 +298420,20 @@ var init_voice = __esm({
|
|
|
298108
298420
|
// -------------------------------------------------------------------------
|
|
298109
298421
|
/** Metadata file for friendly names of clone refs */
|
|
298110
298422
|
static cloneMetaFile() {
|
|
298111
|
-
return
|
|
298423
|
+
return join80(luxttsCloneRefsDir(), "meta.json");
|
|
298112
298424
|
}
|
|
298113
298425
|
loadCloneMeta() {
|
|
298114
298426
|
const p2 = _VoiceEngine.cloneMetaFile();
|
|
298115
|
-
if (!
|
|
298427
|
+
if (!existsSync64(p2)) return {};
|
|
298116
298428
|
try {
|
|
298117
|
-
return JSON.parse(
|
|
298429
|
+
return JSON.parse(readFileSync49(p2, "utf8"));
|
|
298118
298430
|
} catch {
|
|
298119
298431
|
return {};
|
|
298120
298432
|
}
|
|
298121
298433
|
}
|
|
298122
298434
|
saveCloneMeta(meta) {
|
|
298123
298435
|
const dir = luxttsCloneRefsDir();
|
|
298124
|
-
if (!
|
|
298436
|
+
if (!existsSync64(dir)) mkdirSync36(dir, { recursive: true });
|
|
298125
298437
|
writeFileSync33(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
|
|
298126
298438
|
}
|
|
298127
298439
|
/** Audio file extensions recognized as clone references */
|
|
@@ -298132,14 +298444,14 @@ var init_voice = __esm({
|
|
|
298132
298444
|
*/
|
|
298133
298445
|
listCloneRefs() {
|
|
298134
298446
|
const dir = luxttsCloneRefsDir();
|
|
298135
|
-
if (!
|
|
298447
|
+
if (!existsSync64(dir)) return [];
|
|
298136
298448
|
const meta = this.loadCloneMeta();
|
|
298137
298449
|
const files = readdirSync16(dir).filter((f2) => {
|
|
298138
298450
|
const ext = f2.split(".").pop()?.toLowerCase() ?? "";
|
|
298139
298451
|
return _VoiceEngine.AUDIO_EXTS.has(ext);
|
|
298140
298452
|
});
|
|
298141
298453
|
return files.map((f2) => {
|
|
298142
|
-
const p2 =
|
|
298454
|
+
const p2 = join80(dir, f2);
|
|
298143
298455
|
let size = 0;
|
|
298144
298456
|
try {
|
|
298145
298457
|
size = statSync18(p2).size;
|
|
@@ -298156,8 +298468,8 @@ var init_voice = __esm({
|
|
|
298156
298468
|
}
|
|
298157
298469
|
/** Delete a clone reference file by filename. Returns true if deleted. */
|
|
298158
298470
|
deleteCloneRef(filename) {
|
|
298159
|
-
const p2 =
|
|
298160
|
-
if (!
|
|
298471
|
+
const p2 = join80(luxttsCloneRefsDir(), filename);
|
|
298472
|
+
if (!existsSync64(p2)) return false;
|
|
298161
298473
|
try {
|
|
298162
298474
|
unlinkSync17(p2);
|
|
298163
298475
|
const meta = this.loadCloneMeta();
|
|
@@ -298180,8 +298492,8 @@ var init_voice = __esm({
|
|
|
298180
298492
|
}
|
|
298181
298493
|
/** Set the active clone reference by filename. */
|
|
298182
298494
|
setActiveCloneRef(filename) {
|
|
298183
|
-
const p2 =
|
|
298184
|
-
if (!
|
|
298495
|
+
const p2 = join80(luxttsCloneRefsDir(), filename);
|
|
298496
|
+
if (!existsSync64(p2)) return `File not found: ${filename}`;
|
|
298185
298497
|
this.luxttsCloneRef = p2;
|
|
298186
298498
|
return `Active clone voice set to: ${filename}`;
|
|
298187
298499
|
}
|
|
@@ -298518,7 +298830,7 @@ var init_voice = __esm({
|
|
|
298518
298830
|
}
|
|
298519
298831
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
298520
298832
|
}
|
|
298521
|
-
const wavPath =
|
|
298833
|
+
const wavPath = join80(tmpdir19(), `oa-voice-${Date.now()}.wav`);
|
|
298522
298834
|
this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
|
|
298523
298835
|
await this.playWav(wavPath);
|
|
298524
298836
|
try {
|
|
@@ -298914,7 +299226,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298914
299226
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
298915
299227
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
298916
299228
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
298917
|
-
const wavPath =
|
|
299229
|
+
const wavPath = join80(tmpdir19(), `oa-mlx-${Date.now()}.wav`);
|
|
298918
299230
|
const pyScript = [
|
|
298919
299231
|
"import sys, json",
|
|
298920
299232
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -298937,10 +299249,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298937
299249
|
return;
|
|
298938
299250
|
}
|
|
298939
299251
|
}
|
|
298940
|
-
if (!
|
|
299252
|
+
if (!existsSync64(wavPath)) return;
|
|
298941
299253
|
if (volume !== 1) {
|
|
298942
299254
|
try {
|
|
298943
|
-
const wavData =
|
|
299255
|
+
const wavData = readFileSync49(wavPath);
|
|
298944
299256
|
if (wavData.length > 44) {
|
|
298945
299257
|
const header = wavData.subarray(0, 44);
|
|
298946
299258
|
const samples = new Int16Array(
|
|
@@ -298959,7 +299271,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298959
299271
|
}
|
|
298960
299272
|
if (this.onPCMOutput) {
|
|
298961
299273
|
try {
|
|
298962
|
-
const wavData =
|
|
299274
|
+
const wavData = readFileSync49(wavPath);
|
|
298963
299275
|
if (wavData.length > 44) {
|
|
298964
299276
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
298965
299277
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -298988,7 +299300,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298988
299300
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
298989
299301
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
298990
299302
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
298991
|
-
const wavPath =
|
|
299303
|
+
const wavPath = join80(tmpdir19(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
298992
299304
|
const pyScript = [
|
|
298993
299305
|
"import sys, json",
|
|
298994
299306
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -299011,9 +299323,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299011
299323
|
return null;
|
|
299012
299324
|
}
|
|
299013
299325
|
}
|
|
299014
|
-
if (!
|
|
299326
|
+
if (!existsSync64(wavPath)) return null;
|
|
299015
299327
|
try {
|
|
299016
|
-
const data =
|
|
299328
|
+
const data = readFileSync49(wavPath);
|
|
299017
299329
|
unlinkSync17(wavPath);
|
|
299018
299330
|
return data;
|
|
299019
299331
|
} catch {
|
|
@@ -299038,7 +299350,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299038
299350
|
}
|
|
299039
299351
|
const venvDir = luxttsVenvDir();
|
|
299040
299352
|
const venvPy = luxttsVenvPy();
|
|
299041
|
-
if (
|
|
299353
|
+
if (existsSync64(venvPy)) {
|
|
299042
299354
|
try {
|
|
299043
299355
|
const quotedPy = `"${venvPy}"`;
|
|
299044
299356
|
const repoPath = luxttsRepoDir().replace(/\\/g, "/");
|
|
@@ -299060,7 +299372,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299060
299372
|
if (torchCheck === "cpu") {
|
|
299061
299373
|
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
|
|
299062
299374
|
try {
|
|
299063
|
-
const detectScript =
|
|
299375
|
+
const detectScript = join80(voiceDir(), "detect-torch.py");
|
|
299064
299376
|
writeDetectTorchScript(detectScript);
|
|
299065
299377
|
let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
|
|
299066
299378
|
try {
|
|
@@ -299087,7 +299399,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299087
299399
|
}
|
|
299088
299400
|
}
|
|
299089
299401
|
renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
|
|
299090
|
-
if (!
|
|
299402
|
+
if (!existsSync64(venvDir)) {
|
|
299091
299403
|
renderInfo(" Creating Python virtual environment...");
|
|
299092
299404
|
try {
|
|
299093
299405
|
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
@@ -299098,7 +299410,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299098
299410
|
}
|
|
299099
299411
|
}
|
|
299100
299412
|
{
|
|
299101
|
-
const detectScript =
|
|
299413
|
+
const detectScript = join80(voiceDir(), "detect-torch.py");
|
|
299102
299414
|
writeDetectTorchScript(detectScript);
|
|
299103
299415
|
let pipArgsStr = "torch torchaudio";
|
|
299104
299416
|
let torchDesc = "unknown platform";
|
|
@@ -299143,10 +299455,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299143
299455
|
}
|
|
299144
299456
|
}
|
|
299145
299457
|
const repoDir = luxttsRepoDir();
|
|
299146
|
-
if (!
|
|
299458
|
+
if (!existsSync64(join80(repoDir, "zipvoice", "luxvoice.py"))) {
|
|
299147
299459
|
renderInfo(" Cloning LuxTTS repository...");
|
|
299148
299460
|
try {
|
|
299149
|
-
if (
|
|
299461
|
+
if (existsSync64(repoDir)) {
|
|
299150
299462
|
const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
|
|
299151
299463
|
await this.asyncShell(rmCmd, 3e4);
|
|
299152
299464
|
}
|
|
@@ -299235,7 +299547,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299235
299547
|
renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
|
|
299236
299548
|
}
|
|
299237
299549
|
}
|
|
299238
|
-
const isJetson = isArm && (
|
|
299550
|
+
const isJetson = isArm && (existsSync64("/etc/nv_tegra_release") || existsSync64("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
|
|
299239
299551
|
const installSteps = isArm ? [
|
|
299240
299552
|
// ARM: install individually so we get clear error messages per package.
|
|
299241
299553
|
// ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
|
|
@@ -299248,7 +299560,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299248
299560
|
...isJetson ? (() => {
|
|
299249
299561
|
let jpVer = "v60";
|
|
299250
299562
|
try {
|
|
299251
|
-
const tegra =
|
|
299563
|
+
const tegra = existsSync64("/etc/nv_tegra_release") ? execSync50("cat /etc/nv_tegra_release 2>/dev/null", { encoding: "utf8", timeout: 3e3 }).trim() : "";
|
|
299252
299564
|
const dpkg = execSync50("dpkg -l nvidia-jetpack 2>/dev/null | grep nvidia-jetpack | awk '{print $3}'", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
299253
299565
|
const ver = dpkg || process.env.JETSON_L4T_VERSION || "";
|
|
299254
299566
|
if (ver.startsWith("5.") || tegra.includes("R35") || tegra.includes("R34")) jpVer = "v51";
|
|
@@ -299328,12 +299640,12 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299328
299640
|
}
|
|
299329
299641
|
/** Auto-detect an existing clone reference in the refs directory */
|
|
299330
299642
|
autoDetectCloneRef() {
|
|
299331
|
-
if (this.luxttsCloneRef &&
|
|
299643
|
+
if (this.luxttsCloneRef && existsSync64(this.luxttsCloneRef)) return;
|
|
299332
299644
|
const refsDir = luxttsCloneRefsDir();
|
|
299333
|
-
if (!
|
|
299645
|
+
if (!existsSync64(refsDir)) return;
|
|
299334
299646
|
for (const name10 of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
|
|
299335
|
-
const p2 =
|
|
299336
|
-
if (
|
|
299647
|
+
const p2 = join80(refsDir, name10);
|
|
299648
|
+
if (existsSync64(p2)) {
|
|
299337
299649
|
this.luxttsCloneRef = p2;
|
|
299338
299650
|
return;
|
|
299339
299651
|
}
|
|
@@ -299440,7 +299752,7 @@ if __name__ == '__main__':
|
|
|
299440
299752
|
async ensureLuxttsDaemon() {
|
|
299441
299753
|
if (this._luxttsDaemon && !this._luxttsDaemon.killed) return true;
|
|
299442
299754
|
const venvPy = luxttsVenvPy();
|
|
299443
|
-
if (!
|
|
299755
|
+
if (!existsSync64(venvPy)) return false;
|
|
299444
299756
|
return new Promise((resolve39) => {
|
|
299445
299757
|
const env2 = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
299446
299758
|
const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
|
|
@@ -299529,12 +299841,12 @@ if __name__ == '__main__':
|
|
|
299529
299841
|
* Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
|
|
299530
299842
|
*/
|
|
299531
299843
|
async synthesizeLuxttsWav(text, speedFactor = 1) {
|
|
299532
|
-
if (!this.luxttsCloneRef || !
|
|
299844
|
+
if (!this.luxttsCloneRef || !existsSync64(this.luxttsCloneRef)) return null;
|
|
299533
299845
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
299534
299846
|
if (!cleaned) return null;
|
|
299535
299847
|
const ready = await this.ensureLuxttsDaemon();
|
|
299536
299848
|
if (!ready) return null;
|
|
299537
|
-
const wavPath =
|
|
299849
|
+
const wavPath = join80(tmpdir19(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
|
|
299538
299850
|
try {
|
|
299539
299851
|
await this.luxttsRequest({
|
|
299540
299852
|
action: "synthesize",
|
|
@@ -299546,16 +299858,16 @@ if __name__ == '__main__':
|
|
|
299546
299858
|
} catch {
|
|
299547
299859
|
return null;
|
|
299548
299860
|
}
|
|
299549
|
-
return
|
|
299861
|
+
return existsSync64(wavPath) ? wavPath : null;
|
|
299550
299862
|
}
|
|
299551
299863
|
/**
|
|
299552
299864
|
* Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
|
|
299553
299865
|
* Cleans up the WAV file after playback.
|
|
299554
299866
|
*/
|
|
299555
299867
|
async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
|
|
299556
|
-
if (!
|
|
299868
|
+
if (!existsSync64(wavPath)) return;
|
|
299557
299869
|
try {
|
|
299558
|
-
const wavData =
|
|
299870
|
+
const wavData = readFileSync49(wavPath);
|
|
299559
299871
|
if (wavData.length > 44) {
|
|
299560
299872
|
const sampleRate = wavData.readUInt32LE(24);
|
|
299561
299873
|
const samples = new Int16Array(
|
|
@@ -299580,7 +299892,7 @@ if __name__ == '__main__':
|
|
|
299580
299892
|
}
|
|
299581
299893
|
if (pitchFactor !== 1) {
|
|
299582
299894
|
try {
|
|
299583
|
-
const wavData =
|
|
299895
|
+
const wavData = readFileSync49(wavPath);
|
|
299584
299896
|
if (wavData.length > 44) {
|
|
299585
299897
|
const int16 = new Int16Array(
|
|
299586
299898
|
wavData.buffer,
|
|
@@ -299599,7 +299911,7 @@ if __name__ == '__main__':
|
|
|
299599
299911
|
}
|
|
299600
299912
|
if (this.onPCMOutput) {
|
|
299601
299913
|
try {
|
|
299602
|
-
const wavData =
|
|
299914
|
+
const wavData = readFileSync49(wavPath);
|
|
299603
299915
|
if (wavData.length > 44) {
|
|
299604
299916
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
299605
299917
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -299610,7 +299922,7 @@ if __name__ == '__main__':
|
|
|
299610
299922
|
}
|
|
299611
299923
|
if (stereoDelayMs > 0) {
|
|
299612
299924
|
try {
|
|
299613
|
-
const wavData =
|
|
299925
|
+
const wavData = readFileSync49(wavPath);
|
|
299614
299926
|
if (wavData.length > 44) {
|
|
299615
299927
|
const sampleRate = wavData.readUInt32LE(24);
|
|
299616
299928
|
const numChannels = wavData.readUInt16LE(22);
|
|
@@ -299649,12 +299961,12 @@ if __name__ == '__main__':
|
|
|
299649
299961
|
* Used for Telegram voice messages and WebSocket streaming.
|
|
299650
299962
|
*/
|
|
299651
299963
|
async synthesizeLuxttsToBuffer(text) {
|
|
299652
|
-
if (!this.luxttsCloneRef || !
|
|
299964
|
+
if (!this.luxttsCloneRef || !existsSync64(this.luxttsCloneRef)) return null;
|
|
299653
299965
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
299654
299966
|
if (!cleaned) return null;
|
|
299655
299967
|
const ready = await this.ensureLuxttsDaemon();
|
|
299656
299968
|
if (!ready) return null;
|
|
299657
|
-
const wavPath =
|
|
299969
|
+
const wavPath = join80(tmpdir19(), `oa-luxtts-buf-${Date.now()}.wav`);
|
|
299658
299970
|
try {
|
|
299659
299971
|
await this.luxttsRequest({
|
|
299660
299972
|
action: "synthesize",
|
|
@@ -299666,9 +299978,9 @@ if __name__ == '__main__':
|
|
|
299666
299978
|
} catch {
|
|
299667
299979
|
return null;
|
|
299668
299980
|
}
|
|
299669
|
-
if (!
|
|
299981
|
+
if (!existsSync64(wavPath)) return null;
|
|
299670
299982
|
try {
|
|
299671
|
-
const data =
|
|
299983
|
+
const data = readFileSync49(wavPath);
|
|
299672
299984
|
unlinkSync17(wavPath);
|
|
299673
299985
|
return data;
|
|
299674
299986
|
} catch {
|
|
@@ -299682,14 +299994,14 @@ if __name__ == '__main__':
|
|
|
299682
299994
|
if (this.ort) return;
|
|
299683
299995
|
const arch2 = process.arch;
|
|
299684
299996
|
mkdirSync36(voiceDir(), { recursive: true });
|
|
299685
|
-
const pkgPath =
|
|
299997
|
+
const pkgPath = join80(voiceDir(), "package.json");
|
|
299686
299998
|
const expectedDeps = {
|
|
299687
299999
|
"onnxruntime-node": "^1.21.0",
|
|
299688
300000
|
"phonemizer": "^1.2.1"
|
|
299689
300001
|
};
|
|
299690
|
-
if (
|
|
300002
|
+
if (existsSync64(pkgPath)) {
|
|
299691
300003
|
try {
|
|
299692
|
-
const existing = JSON.parse(
|
|
300004
|
+
const existing = JSON.parse(readFileSync49(pkgPath, "utf8"));
|
|
299693
300005
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
299694
300006
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
299695
300007
|
writeFileSync33(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -299697,18 +300009,18 @@ if __name__ == '__main__':
|
|
|
299697
300009
|
} catch {
|
|
299698
300010
|
}
|
|
299699
300011
|
}
|
|
299700
|
-
if (!
|
|
300012
|
+
if (!existsSync64(pkgPath)) {
|
|
299701
300013
|
writeFileSync33(pkgPath, JSON.stringify({
|
|
299702
300014
|
name: "open-agents-voice",
|
|
299703
300015
|
private: true,
|
|
299704
300016
|
dependencies: expectedDeps
|
|
299705
300017
|
}, null, 2));
|
|
299706
300018
|
}
|
|
299707
|
-
const voiceRequire = createRequire3(
|
|
300019
|
+
const voiceRequire = createRequire3(join80(voiceDir(), "index.js"));
|
|
299708
300020
|
const probeOnnx = async () => {
|
|
299709
300021
|
try {
|
|
299710
300022
|
const output = await this.asyncShell(
|
|
299711
|
-
`NODE_PATH="${
|
|
300023
|
+
`NODE_PATH="${join80(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`,
|
|
299712
300024
|
15e3
|
|
299713
300025
|
);
|
|
299714
300026
|
return output.trim() === "OK";
|
|
@@ -299716,8 +300028,8 @@ if __name__ == '__main__':
|
|
|
299716
300028
|
return false;
|
|
299717
300029
|
}
|
|
299718
300030
|
};
|
|
299719
|
-
const onnxNodeModules =
|
|
299720
|
-
const onnxInstalled =
|
|
300031
|
+
const onnxNodeModules = join80(voiceDir(), "node_modules", "onnxruntime-node");
|
|
300032
|
+
const onnxInstalled = existsSync64(onnxNodeModules);
|
|
299721
300033
|
if (onnxInstalled && !await probeOnnx()) {
|
|
299722
300034
|
throw new Error(
|
|
299723
300035
|
`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`
|
|
@@ -299776,16 +300088,16 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299776
300088
|
const dir = modelDir(id);
|
|
299777
300089
|
const onnxPath = modelOnnxPath(id);
|
|
299778
300090
|
const configPath2 = modelConfigPath(id);
|
|
299779
|
-
if (
|
|
300091
|
+
if (existsSync64(onnxPath) && existsSync64(configPath2)) return;
|
|
299780
300092
|
mkdirSync36(dir, { recursive: true });
|
|
299781
|
-
if (!
|
|
300093
|
+
if (!existsSync64(configPath2)) {
|
|
299782
300094
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
299783
300095
|
const configResp = await fetch(model.configUrl);
|
|
299784
300096
|
if (!configResp.ok) throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
299785
300097
|
const configText = await configResp.text();
|
|
299786
300098
|
writeFileSync33(configPath2, configText);
|
|
299787
300099
|
}
|
|
299788
|
-
if (!
|
|
300100
|
+
if (!existsSync64(onnxPath)) {
|
|
299789
300101
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
299790
300102
|
const onnxResp = await fetch(model.onnxUrl);
|
|
299791
300103
|
if (!onnxResp.ok) throw new Error(`Failed to download model: HTTP ${onnxResp.status}`);
|
|
@@ -299818,10 +300130,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299818
300130
|
if (!this.ort) throw new Error("ONNX runtime not loaded");
|
|
299819
300131
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
299820
300132
|
const configPath2 = modelConfigPath(this.modelId);
|
|
299821
|
-
if (!
|
|
300133
|
+
if (!existsSync64(onnxPath) || !existsSync64(configPath2)) {
|
|
299822
300134
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
299823
300135
|
}
|
|
299824
|
-
this.config = JSON.parse(
|
|
300136
|
+
this.config = JSON.parse(readFileSync49(configPath2, "utf8"));
|
|
299825
300137
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
299826
300138
|
executionProviders: ["cpu"],
|
|
299827
300139
|
graphOptimizationLevel: "all"
|
|
@@ -299848,8 +300160,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299848
300160
|
// packages/cli/src/tui/commands.ts
|
|
299849
300161
|
import * as nodeOs from "node:os";
|
|
299850
300162
|
import { execSync as nodeExecSync } from "node:child_process";
|
|
299851
|
-
import { existsSync as
|
|
299852
|
-
import { join as
|
|
300163
|
+
import { existsSync as existsSync65, readFileSync as readFileSync50, writeFileSync as writeFileSync34, mkdirSync as mkdirSync37, readdirSync as readdirSync17, statSync as statSync19, rmSync as rmSync2, appendFileSync as appendFileSync3 } from "node:fs";
|
|
300164
|
+
import { join as join81 } from "node:path";
|
|
299853
300165
|
async function _immediateReregister(newUrl) {
|
|
299854
300166
|
if (!_lastRegisteredSponsorPayload) return;
|
|
299855
300167
|
_lastRegisteredSponsorPayload.tunnelUrl = newUrl;
|
|
@@ -300362,9 +300674,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300362
300674
|
if (out.includes("Connected") || out.includes("Already connected")) {
|
|
300363
300675
|
renderInfo(out.split("\n").slice(0, 4).join("\n"));
|
|
300364
300676
|
try {
|
|
300365
|
-
const pidFile =
|
|
300366
|
-
if (
|
|
300367
|
-
const pid = parseInt(
|
|
300677
|
+
const pidFile = join81(ctx3.repoRoot ?? process.cwd(), ".oa", "nexus", "daemon.pid");
|
|
300678
|
+
if (existsSync65(pidFile)) {
|
|
300679
|
+
const pid = parseInt(readFileSync50(pidFile, "utf8").trim(), 10);
|
|
300368
300680
|
if (pid > 0 && !registry2.daemons.has("Nexus")) {
|
|
300369
300681
|
registry2.register({ name: "Nexus", pid, startedAt: Date.now(), status: "running" });
|
|
300370
300682
|
}
|
|
@@ -300668,22 +300980,22 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300668
300980
|
let content = "";
|
|
300669
300981
|
let metadata = {};
|
|
300670
300982
|
if (shareType === "tool") {
|
|
300671
|
-
const toolDir =
|
|
300672
|
-
const toolFile =
|
|
300673
|
-
if (!
|
|
300983
|
+
const toolDir = join81(ctx3.repoRoot, ".oa", "tools");
|
|
300984
|
+
const toolFile = join81(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
|
|
300985
|
+
if (!existsSync65(toolFile)) {
|
|
300674
300986
|
renderWarning(`Tool not found: ${toolFile}`);
|
|
300675
300987
|
return "handled";
|
|
300676
300988
|
}
|
|
300677
|
-
content =
|
|
300989
|
+
content = readFileSync50(toolFile, "utf8");
|
|
300678
300990
|
metadata = { type: "tool", name: shareName };
|
|
300679
300991
|
} else if (shareType === "skill") {
|
|
300680
|
-
const skillDir =
|
|
300681
|
-
const skillFile =
|
|
300682
|
-
if (!
|
|
300992
|
+
const skillDir = join81(ctx3.repoRoot, ".oa", "skills", shareName);
|
|
300993
|
+
const skillFile = join81(skillDir, "SKILL.md");
|
|
300994
|
+
if (!existsSync65(skillFile)) {
|
|
300683
300995
|
renderWarning(`Skill not found: ${skillFile}`);
|
|
300684
300996
|
return "handled";
|
|
300685
300997
|
}
|
|
300686
|
-
content =
|
|
300998
|
+
content = readFileSync50(skillFile, "utf8");
|
|
300687
300999
|
metadata = { type: "skill", name: shareName };
|
|
300688
301000
|
} else {
|
|
300689
301001
|
renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
|
|
@@ -300720,9 +301032,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300720
301032
|
try {
|
|
300721
301033
|
const nexus = new NexusTool(ctx3.repoRoot);
|
|
300722
301034
|
await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
|
|
300723
|
-
const regFile =
|
|
300724
|
-
if (
|
|
300725
|
-
const reg = JSON.parse(
|
|
301035
|
+
const regFile = join81(ctx3.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
|
|
301036
|
+
if (existsSync65(regFile)) {
|
|
301037
|
+
const reg = JSON.parse(readFileSync50(regFile, "utf8"));
|
|
300726
301038
|
const pinned = Object.values(reg).some((e2) => e2.cid === importCid && e2.pinned);
|
|
300727
301039
|
if (pinned) {
|
|
300728
301040
|
renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
|
|
@@ -300773,32 +301085,32 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300773
301085
|
lines.push(`
|
|
300774
301086
|
${c3.bold("IPFS / Helia Status")}
|
|
300775
301087
|
`);
|
|
300776
|
-
const ipfsDir =
|
|
300777
|
-
const ipfsLocalDir =
|
|
301088
|
+
const ipfsDir = join81(ctx3.repoRoot, ".oa", "ipfs");
|
|
301089
|
+
const ipfsLocalDir = join81(ipfsDir, "local");
|
|
300778
301090
|
let ipfsFiles = 0;
|
|
300779
301091
|
let ipfsBytes = 0;
|
|
300780
301092
|
let heliaBlocks = 0;
|
|
300781
301093
|
let heliaBytes = 0;
|
|
300782
301094
|
try {
|
|
300783
|
-
if (
|
|
301095
|
+
if (existsSync65(ipfsLocalDir)) {
|
|
300784
301096
|
const files = readdirSync17(ipfsLocalDir).filter((f2) => f2.endsWith(".json"));
|
|
300785
301097
|
ipfsFiles = files.length;
|
|
300786
301098
|
for (const f2 of files) {
|
|
300787
301099
|
try {
|
|
300788
|
-
ipfsBytes += statSync19(
|
|
301100
|
+
ipfsBytes += statSync19(join81(ipfsLocalDir, f2)).size;
|
|
300789
301101
|
} catch {
|
|
300790
301102
|
}
|
|
300791
301103
|
}
|
|
300792
301104
|
}
|
|
300793
|
-
const heliaBlockDir =
|
|
300794
|
-
if (
|
|
301105
|
+
const heliaBlockDir = join81(ipfsDir, "blocks");
|
|
301106
|
+
if (existsSync65(heliaBlockDir)) {
|
|
300795
301107
|
const walkDir = (dir) => {
|
|
300796
301108
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300797
|
-
if (entry.isDirectory()) walkDir(
|
|
301109
|
+
if (entry.isDirectory()) walkDir(join81(dir, entry.name));
|
|
300798
301110
|
else {
|
|
300799
301111
|
heliaBlocks++;
|
|
300800
301112
|
try {
|
|
300801
|
-
heliaBytes += statSync19(
|
|
301113
|
+
heliaBytes += statSync19(join81(dir, entry.name)).size;
|
|
300802
301114
|
} catch {
|
|
300803
301115
|
}
|
|
300804
301116
|
}
|
|
@@ -300814,9 +301126,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300814
301126
|
lines.push(` Blocks: ${c3.bold(String(heliaBlocks))} Size: ${c3.bold(formatFileSize(heliaBytes))}`);
|
|
300815
301127
|
lines.push(` Backend: ${heliaBlocks > 0 ? c3.green("helia-ipfs") : c3.yellow("sha256-local (Helia not initialized)")}`);
|
|
300816
301128
|
try {
|
|
300817
|
-
const statusFile =
|
|
300818
|
-
if (
|
|
300819
|
-
const status = JSON.parse(
|
|
301129
|
+
const statusFile = join81(ctx3.repoRoot, ".oa", "nexus", "status.json");
|
|
301130
|
+
if (existsSync65(statusFile)) {
|
|
301131
|
+
const status = JSON.parse(readFileSync50(statusFile, "utf8"));
|
|
300820
301132
|
if (status.peerId) {
|
|
300821
301133
|
lines.push(`
|
|
300822
301134
|
${c3.bold("Peer Info")}`);
|
|
@@ -300835,11 +301147,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300835
301147
|
${c3.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
|
|
300836
301148
|
lines.push(`
|
|
300837
301149
|
${c3.bold("Identity Kernel")}`);
|
|
300838
|
-
const idDir =
|
|
301150
|
+
const idDir = join81(ctx3.repoRoot, ".oa", "identity");
|
|
300839
301151
|
try {
|
|
300840
|
-
const stateFile =
|
|
300841
|
-
if (
|
|
300842
|
-
const state = JSON.parse(
|
|
301152
|
+
const stateFile = join81(idDir, "self-state.json");
|
|
301153
|
+
if (existsSync65(stateFile)) {
|
|
301154
|
+
const state = JSON.parse(readFileSync50(stateFile, "utf8"));
|
|
300843
301155
|
lines.push(` Version: ${c3.bold("v" + (state.version ?? "?"))} Sessions: ${c3.bold(String(state.session_count ?? 0))}`);
|
|
300844
301156
|
if (state.narrative_summary) {
|
|
300845
301157
|
lines.push(` Narrative: ${c3.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
|
|
@@ -300848,9 +301160,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300848
301160
|
const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
|
|
300849
301161
|
lines.push(` Traits: ${c3.dim(traits.slice(0, 60))}`);
|
|
300850
301162
|
}
|
|
300851
|
-
const cidFile =
|
|
300852
|
-
if (
|
|
300853
|
-
const cids = JSON.parse(
|
|
301163
|
+
const cidFile = join81(idDir, "cids.json");
|
|
301164
|
+
if (existsSync65(cidFile)) {
|
|
301165
|
+
const cids = JSON.parse(readFileSync50(cidFile, "utf8"));
|
|
300854
301166
|
const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
|
|
300855
301167
|
if (lastCid) lines.push(` Last CID: ${c3.dim(String(lastCid).slice(0, 50))}`);
|
|
300856
301168
|
}
|
|
@@ -300862,9 +301174,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300862
301174
|
lines.push(`
|
|
300863
301175
|
${c3.bold("Memory Sentiment")}`);
|
|
300864
301176
|
try {
|
|
300865
|
-
const metaFile =
|
|
300866
|
-
if (
|
|
300867
|
-
const store2 = JSON.parse(
|
|
301177
|
+
const metaFile = join81(ctx3.repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
301178
|
+
if (existsSync65(metaFile)) {
|
|
301179
|
+
const store2 = JSON.parse(readFileSync50(metaFile, "utf8"));
|
|
300868
301180
|
const active = store2.filter((m2) => m2.type !== "quarantine");
|
|
300869
301181
|
const recoveries = active.filter((m2) => m2.content?.startsWith("[recovery]")).length;
|
|
300870
301182
|
const strategies = active.filter((m2) => m2.content?.startsWith("[strategy]")).length;
|
|
@@ -300882,8 +301194,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300882
301194
|
} catch {
|
|
300883
301195
|
}
|
|
300884
301196
|
try {
|
|
300885
|
-
const dbPath =
|
|
300886
|
-
if (
|
|
301197
|
+
const dbPath = join81(ctx3.repoRoot, ".oa", "memory", "structured.db");
|
|
301198
|
+
if (existsSync65(dbPath)) {
|
|
300887
301199
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
300888
301200
|
const db = initDb2(dbPath);
|
|
300889
301201
|
const memStore = new ProceduralMemoryStore2(db);
|
|
@@ -300904,8 +301216,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300904
301216
|
lines.push(`
|
|
300905
301217
|
${c3.bold("Storage Overview")}
|
|
300906
301218
|
`);
|
|
300907
|
-
const oaDir =
|
|
300908
|
-
if (!
|
|
301219
|
+
const oaDir = join81(ctx3.repoRoot, ".oa");
|
|
301220
|
+
if (!existsSync65(oaDir)) {
|
|
300909
301221
|
lines.push(` ${c3.dim("No .oa/ directory found.")}`);
|
|
300910
301222
|
safeLog(lines.join("\n") + "\n");
|
|
300911
301223
|
return "handled";
|
|
@@ -300915,7 +301227,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300915
301227
|
const walkStorage = (dir, category) => {
|
|
300916
301228
|
try {
|
|
300917
301229
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300918
|
-
const full =
|
|
301230
|
+
const full = join81(dir, entry.name);
|
|
300919
301231
|
if (entry.isDirectory()) {
|
|
300920
301232
|
const subCat = category || entry.name;
|
|
300921
301233
|
walkStorage(full, subCat);
|
|
@@ -300950,9 +301262,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300950
301262
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300951
301263
|
const name10 = entry.name.toLowerCase();
|
|
300952
301264
|
if (sensitivePatterns.some((p2) => name10.includes(p2))) {
|
|
300953
|
-
sensitiveFound.push(
|
|
301265
|
+
sensitiveFound.push(join81(dir, entry.name).replace(oaDir + "/", ""));
|
|
300954
301266
|
}
|
|
300955
|
-
if (entry.isDirectory()) checkSensitive(
|
|
301267
|
+
if (entry.isDirectory()) checkSensitive(join81(dir, entry.name));
|
|
300956
301268
|
}
|
|
300957
301269
|
} catch {
|
|
300958
301270
|
}
|
|
@@ -300980,8 +301292,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300980
301292
|
renderInfo("Supported: .wav .mp3 .flac .ogg (audio→transcribe) | .pdf .txt .md (text→chunk)");
|
|
300981
301293
|
return "handled";
|
|
300982
301294
|
}
|
|
300983
|
-
const resolvedPath =
|
|
300984
|
-
if (!
|
|
301295
|
+
const resolvedPath = join81(ctx3.repoRoot, filePath);
|
|
301296
|
+
if (!existsSync65(resolvedPath)) {
|
|
300985
301297
|
renderWarning(`File not found: ${resolvedPath}`);
|
|
300986
301298
|
return "handled";
|
|
300987
301299
|
}
|
|
@@ -300997,9 +301309,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300997
301309
|
}
|
|
300998
301310
|
try {
|
|
300999
301311
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
301000
|
-
const dbDir =
|
|
301312
|
+
const dbDir = join81(ctx3.repoRoot, ".oa", "memory");
|
|
301001
301313
|
mkdirSync37(dbDir, { recursive: true });
|
|
301002
|
-
const db = initDb2(
|
|
301314
|
+
const db = initDb2(join81(dbDir, "structured.db"));
|
|
301003
301315
|
const memStore = new ProceduralMemoryStore2(db);
|
|
301004
301316
|
if (isAudio) {
|
|
301005
301317
|
renderInfo(`Transcribing: ${filePath}...`);
|
|
@@ -301043,7 +301355,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301043
301355
|
return "handled";
|
|
301044
301356
|
}
|
|
301045
301357
|
} else {
|
|
301046
|
-
content =
|
|
301358
|
+
content = readFileSync50(resolvedPath, "utf8");
|
|
301047
301359
|
}
|
|
301048
301360
|
if (!content.trim()) {
|
|
301049
301361
|
renderWarning("No content extracted.");
|
|
@@ -301081,9 +301393,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301081
301393
|
}
|
|
301082
301394
|
case "fortemi": {
|
|
301083
301395
|
const fortemiSubCmd = (arg || "").trim().toLowerCase();
|
|
301084
|
-
const fortemiDir =
|
|
301085
|
-
const altFortemiDir =
|
|
301086
|
-
const fDir =
|
|
301396
|
+
const fortemiDir = join81(ctx3.repoRoot, "..", "fortemi-react");
|
|
301397
|
+
const altFortemiDir = join81(nodeOs.homedir(), "fortemi-react");
|
|
301398
|
+
const fDir = existsSync65(fortemiDir) ? fortemiDir : existsSync65(altFortemiDir) ? altFortemiDir : null;
|
|
301087
301399
|
if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
|
|
301088
301400
|
if (!fDir) {
|
|
301089
301401
|
renderWarning("fortemi-react not found adjacent or in home directory.");
|
|
@@ -301098,14 +301410,14 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301098
301410
|
// 24h
|
|
301099
301411
|
nonce: Math.random().toString(36).slice(2, 10)
|
|
301100
301412
|
};
|
|
301101
|
-
const jwtFile =
|
|
301102
|
-
mkdirSync37(
|
|
301413
|
+
const jwtFile = join81(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
|
|
301414
|
+
mkdirSync37(join81(ctx3.repoRoot, ".oa"), { recursive: true });
|
|
301103
301415
|
writeFileSync34(jwtFile, JSON.stringify(jwtPayload, null, 2));
|
|
301104
301416
|
renderInfo(`Launching fortemi-react from ${fDir}...`);
|
|
301105
301417
|
try {
|
|
301106
301418
|
const { spawn: spawn27 } = __require("node:child_process");
|
|
301107
301419
|
const child = spawn27("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
|
|
301108
|
-
cwd:
|
|
301420
|
+
cwd: join81(fDir, "apps", "standalone"),
|
|
301109
301421
|
stdio: "ignore",
|
|
301110
301422
|
detached: true,
|
|
301111
301423
|
env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
|
|
@@ -301114,7 +301426,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301114
301426
|
renderInfo("Fortemi-React starting on http://localhost:3000");
|
|
301115
301427
|
renderInfo(`JWT saved to ${jwtFile}`);
|
|
301116
301428
|
renderInfo("Memory operations will proxy to fortemi when available.");
|
|
301117
|
-
const bridgeFile =
|
|
301429
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301118
301430
|
writeFileSync34(bridgeFile, JSON.stringify({
|
|
301119
301431
|
url: "http://localhost:3000",
|
|
301120
301432
|
pid: child.pid,
|
|
@@ -301127,12 +301439,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301127
301439
|
return "handled";
|
|
301128
301440
|
}
|
|
301129
301441
|
if (fortemiSubCmd === "status") {
|
|
301130
|
-
const bridgeFile =
|
|
301131
|
-
if (!
|
|
301442
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301443
|
+
if (!existsSync65(bridgeFile)) {
|
|
301132
301444
|
renderInfo("Fortemi bridge: not connected. Run /fortemi start");
|
|
301133
301445
|
return "handled";
|
|
301134
301446
|
}
|
|
301135
|
-
const bridge = JSON.parse(
|
|
301447
|
+
const bridge = JSON.parse(readFileSync50(bridgeFile, "utf8"));
|
|
301136
301448
|
let alive = false;
|
|
301137
301449
|
try {
|
|
301138
301450
|
process.kill(bridge.pid, 0);
|
|
@@ -301152,15 +301464,15 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301152
301464
|
lines.push(` Process: ${alive ? c3.green("running") : c3.yellow("not running")} (PID ${bridge.pid})`);
|
|
301153
301465
|
lines.push(` HTTP: ${httpOk ? c3.green("connected") : c3.yellow("unreachable")}`);
|
|
301154
301466
|
lines.push(` Started: ${bridge.startedAt}`);
|
|
301155
|
-
lines.push(` JWT: ${
|
|
301467
|
+
lines.push(` JWT: ${existsSync65(bridge.jwtFile) ? c3.green("valid") : c3.yellow("missing")}`);
|
|
301156
301468
|
lines.push("");
|
|
301157
301469
|
safeLog(lines.join("\n"));
|
|
301158
301470
|
return "handled";
|
|
301159
301471
|
}
|
|
301160
301472
|
if (fortemiSubCmd === "stop") {
|
|
301161
|
-
const bridgeFile =
|
|
301162
|
-
if (
|
|
301163
|
-
const bridge = JSON.parse(
|
|
301473
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301474
|
+
if (existsSync65(bridgeFile)) {
|
|
301475
|
+
const bridge = JSON.parse(readFileSync50(bridgeFile, "utf8"));
|
|
301164
301476
|
try {
|
|
301165
301477
|
process.kill(bridge.pid, "SIGTERM");
|
|
301166
301478
|
} catch {
|
|
@@ -301612,11 +301924,24 @@ Clone a new voice: /voice clone <wav-file> [name]`);
|
|
|
301612
301924
|
case "neovim":
|
|
301613
301925
|
case "nvim":
|
|
301614
301926
|
case "vim": {
|
|
301927
|
+
const tasksRenderer = await Promise.resolve().then(() => (init_tui_tasks_renderer(), tui_tasks_renderer_exports)).catch(() => null);
|
|
301615
301928
|
if (isNeovimActive()) {
|
|
301616
301929
|
await stopNeovimMode();
|
|
301617
301930
|
ctx3.clearScreen();
|
|
301618
301931
|
renderInfo("Neovim mode stopped. Main waterfall restored.");
|
|
301932
|
+
try {
|
|
301933
|
+
tasksRenderer?.setTuiTasksScope({ neovimActive: false });
|
|
301934
|
+
} catch {
|
|
301935
|
+
}
|
|
301936
|
+
try {
|
|
301937
|
+
tasksRenderer?.refreshTuiTasks();
|
|
301938
|
+
} catch {
|
|
301939
|
+
}
|
|
301619
301940
|
} else {
|
|
301941
|
+
try {
|
|
301942
|
+
tasksRenderer?.setTuiTasksScope({ neovimActive: true });
|
|
301943
|
+
} catch {
|
|
301944
|
+
}
|
|
301620
301945
|
ctx3.retireCarousel?.();
|
|
301621
301946
|
const L = layout();
|
|
301622
301947
|
const contentRows = ctx3.availableContentRows?.() ?? Math.max(5, L.contentHeight);
|
|
@@ -301970,9 +302295,9 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
301970
302295
|
}
|
|
301971
302296
|
}
|
|
301972
302297
|
}
|
|
301973
|
-
const _spLogDir =
|
|
302298
|
+
const _spLogDir = join81(projectDir, ".oa", "sponsor");
|
|
301974
302299
|
mkdirSync37(_spLogDir, { recursive: true });
|
|
301975
|
-
const _spLogFile =
|
|
302300
|
+
const _spLogFile = join81(_spLogDir, "sponsor-startup.log");
|
|
301976
302301
|
const _spLog = (msg) => {
|
|
301977
302302
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
301978
302303
|
`;
|
|
@@ -302082,17 +302407,17 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302082
302407
|
}
|
|
302083
302408
|
if (!sponsorUrl && !sponsorPeerId) {
|
|
302084
302409
|
_spLog("FAILED — no tunnelUrl and no peerId");
|
|
302085
|
-
_spLog(`nexusDir checked: ${
|
|
302086
|
-
_spLog(`status.json exists: ${
|
|
302087
|
-
_spLog(`daemon.pid exists: ${
|
|
302410
|
+
_spLog(`nexusDir checked: ${join81(projectDir, ".oa", "nexus")}`);
|
|
302411
|
+
_spLog(`status.json exists: ${existsSync65(join81(projectDir, ".oa", "nexus", "status.json"))}`);
|
|
302412
|
+
_spLog(`daemon.pid exists: ${existsSync65(join81(projectDir, ".oa", "nexus", "daemon.pid"))}`);
|
|
302088
302413
|
try {
|
|
302089
|
-
const _statusRaw =
|
|
302414
|
+
const _statusRaw = readFileSync50(join81(projectDir, ".oa", "nexus", "status.json"), "utf8");
|
|
302090
302415
|
_spLog(`status.json content: ${_statusRaw.slice(0, 300)}`);
|
|
302091
302416
|
} catch (e2) {
|
|
302092
302417
|
_spLog(`status.json read error: ${e2}`);
|
|
302093
302418
|
}
|
|
302094
302419
|
try {
|
|
302095
|
-
const _errRaw =
|
|
302420
|
+
const _errRaw = readFileSync50(join81(projectDir, ".oa", "nexus", "daemon.err"), "utf8");
|
|
302096
302421
|
_spLog(`daemon.err (last 500): ${_errRaw.slice(-500)}`);
|
|
302097
302422
|
} catch (e2) {
|
|
302098
302423
|
_spLog(`daemon.err read error: ${e2}`);
|
|
@@ -302111,7 +302436,7 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302111
302436
|
try {
|
|
302112
302437
|
const { homedir: homedir39 } = __require("os");
|
|
302113
302438
|
const namePath = __require("path").join(homedir39(), ".open-agents", "agent-name");
|
|
302114
|
-
if (
|
|
302439
|
+
if (existsSync65(namePath)) sponsorName = readFileSync50(namePath, "utf8").trim();
|
|
302115
302440
|
} catch {
|
|
302116
302441
|
}
|
|
302117
302442
|
if (!sponsorName) sponsorName = "OA Sponsor";
|
|
@@ -302186,9 +302511,9 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302186
302511
|
if (result) {
|
|
302187
302512
|
renderInfo("Sponsor wizard completed.");
|
|
302188
302513
|
try {
|
|
302189
|
-
const nexusPidFile =
|
|
302190
|
-
if (
|
|
302191
|
-
const nPid = parseInt(
|
|
302514
|
+
const nexusPidFile = join81(projectDir, ".oa", "nexus", "daemon.pid");
|
|
302515
|
+
if (existsSync65(nexusPidFile)) {
|
|
302516
|
+
const nPid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
|
|
302192
302517
|
if (nPid > 0) {
|
|
302193
302518
|
registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
|
|
302194
302519
|
}
|
|
@@ -303252,13 +303577,13 @@ async function showCohereDashboard(ctx3) {
|
|
|
303252
303577
|
} else if (idResult.key === "view") {
|
|
303253
303578
|
await ik.execute({ operation: "hydrate" });
|
|
303254
303579
|
} else if (idResult.key === "history") {
|
|
303255
|
-
const snapDir =
|
|
303256
|
-
if (
|
|
303580
|
+
const snapDir = join81(ctx3.repoRoot, ".oa", "identity", "snapshots");
|
|
303581
|
+
if (existsSync65(snapDir)) {
|
|
303257
303582
|
const snaps = readdirSync17(snapDir).filter((f2) => f2.endsWith(".json")).sort().reverse();
|
|
303258
303583
|
const snapItems = snaps.slice(0, 20).map((f2) => ({
|
|
303259
303584
|
key: f2,
|
|
303260
303585
|
label: f2.replace(".json", ""),
|
|
303261
|
-
detail: `${formatFileSize(statSync19(
|
|
303586
|
+
detail: `${formatFileSize(statSync19(join81(snapDir, f2)).size)}`
|
|
303262
303587
|
}));
|
|
303263
303588
|
if (snapItems.length > 0) {
|
|
303264
303589
|
await tuiSelect({
|
|
@@ -304261,11 +304586,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
|
|
|
304261
304586
|
}
|
|
304262
304587
|
} catch {
|
|
304263
304588
|
}
|
|
304264
|
-
const sponsorDir2 =
|
|
304265
|
-
const knownFile =
|
|
304589
|
+
const sponsorDir2 = join81(ctx3.repoRoot ?? process.cwd(), ".oa", "sponsor");
|
|
304590
|
+
const knownFile = join81(sponsorDir2, "known-sponsors.json");
|
|
304266
304591
|
try {
|
|
304267
|
-
if (
|
|
304268
|
-
const saved = JSON.parse(
|
|
304592
|
+
if (existsSync65(knownFile)) {
|
|
304593
|
+
const saved = JSON.parse(readFileSync50(knownFile, "utf8"));
|
|
304269
304594
|
for (const s2 of saved) {
|
|
304270
304595
|
if (!sponsors.some((sp) => sp.url === s2.url)) {
|
|
304271
304596
|
sponsors.push({ ...s2, source: "saved" });
|
|
@@ -304416,7 +304741,7 @@ async function handleSponsoredEndpoint(ctx3, local) {
|
|
|
304416
304741
|
const saveKey = selected.url || selected.peerId || selected.name;
|
|
304417
304742
|
try {
|
|
304418
304743
|
mkdirSync37(sponsorDir2, { recursive: true });
|
|
304419
|
-
const existing =
|
|
304744
|
+
const existing = existsSync65(knownFile) ? JSON.parse(readFileSync50(knownFile, "utf8")) : [];
|
|
304420
304745
|
const updated = existing.filter((s2) => (s2.url || s2.peerId || s2.name) !== saveKey);
|
|
304421
304746
|
updated.push(selected);
|
|
304422
304747
|
writeFileSync34(knownFile, JSON.stringify(updated, null, 2), "utf8");
|
|
@@ -306161,10 +306486,10 @@ var init_commands = __esm({
|
|
|
306161
306486
|
});
|
|
306162
306487
|
|
|
306163
306488
|
// packages/cli/src/tui/project-context.ts
|
|
306164
|
-
import { existsSync as
|
|
306165
|
-
import { join as
|
|
306489
|
+
import { existsSync as existsSync66, readFileSync as readFileSync51, readdirSync as readdirSync18 } from "node:fs";
|
|
306490
|
+
import { join as join82, basename as basename13 } from "node:path";
|
|
306166
306491
|
import { execSync as execSync51 } from "node:child_process";
|
|
306167
|
-
import { homedir as
|
|
306492
|
+
import { homedir as homedir30, platform as platform5, release } from "node:os";
|
|
306168
306493
|
function getModelTier(modelName) {
|
|
306169
306494
|
const m2 = modelName.toLowerCase();
|
|
306170
306495
|
const sizeMatch = m2.match(/\b(\d+)b\b/);
|
|
@@ -306193,10 +306518,10 @@ function loadProjectMap(repoRoot) {
|
|
|
306193
306518
|
if (!hasOaDirectory(repoRoot)) {
|
|
306194
306519
|
initOaDirectory(repoRoot);
|
|
306195
306520
|
}
|
|
306196
|
-
const mapPath2 =
|
|
306197
|
-
if (
|
|
306521
|
+
const mapPath2 = join82(repoRoot, OA_DIR, "context", "project-map.md");
|
|
306522
|
+
if (existsSync66(mapPath2)) {
|
|
306198
306523
|
try {
|
|
306199
|
-
const content =
|
|
306524
|
+
const content = readFileSync51(mapPath2, "utf-8");
|
|
306200
306525
|
return content;
|
|
306201
306526
|
} catch {
|
|
306202
306527
|
}
|
|
@@ -306235,27 +306560,27 @@ ${log22}`);
|
|
|
306235
306560
|
}
|
|
306236
306561
|
function loadMemoryContext(repoRoot) {
|
|
306237
306562
|
const sections = [];
|
|
306238
|
-
const oaMemDir =
|
|
306563
|
+
const oaMemDir = join82(repoRoot, OA_DIR, "memory");
|
|
306239
306564
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
306240
306565
|
if (oaEntries) sections.push(oaEntries);
|
|
306241
|
-
const legacyMemDir =
|
|
306242
|
-
if (legacyMemDir !== oaMemDir &&
|
|
306566
|
+
const legacyMemDir = join82(repoRoot, ".open-agents", "memory");
|
|
306567
|
+
if (legacyMemDir !== oaMemDir && existsSync66(legacyMemDir)) {
|
|
306243
306568
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
306244
306569
|
if (legacyEntries) sections.push(legacyEntries);
|
|
306245
306570
|
}
|
|
306246
|
-
const globalMemDir =
|
|
306571
|
+
const globalMemDir = join82(homedir30(), ".open-agents", "memory");
|
|
306247
306572
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
306248
306573
|
if (globalEntries) sections.push(globalEntries);
|
|
306249
306574
|
return sections.join("\n\n");
|
|
306250
306575
|
}
|
|
306251
306576
|
function loadMemoryDir(memDir, scope) {
|
|
306252
|
-
if (!
|
|
306577
|
+
if (!existsSync66(memDir)) return "";
|
|
306253
306578
|
const lines = [];
|
|
306254
306579
|
try {
|
|
306255
306580
|
const files = readdirSync18(memDir).filter((f2) => f2.endsWith(".json"));
|
|
306256
306581
|
for (const file of files.slice(0, 10)) {
|
|
306257
306582
|
try {
|
|
306258
|
-
const raw =
|
|
306583
|
+
const raw = readFileSync51(join82(memDir, file), "utf-8");
|
|
306259
306584
|
const entries = JSON.parse(raw);
|
|
306260
306585
|
const topic = basename13(file, ".json");
|
|
306261
306586
|
const keys = Object.keys(entries);
|
|
@@ -306760,8 +307085,8 @@ __export(banner_exports, {
|
|
|
306760
307085
|
saveBannerDesign: () => saveBannerDesign,
|
|
306761
307086
|
setGridText: () => setGridText
|
|
306762
307087
|
});
|
|
306763
|
-
import { existsSync as
|
|
306764
|
-
import { join as
|
|
307088
|
+
import { existsSync as existsSync67, readFileSync as readFileSync52, writeFileSync as writeFileSync35, mkdirSync as mkdirSync38 } from "node:fs";
|
|
307089
|
+
import { join as join83 } from "node:path";
|
|
306765
307090
|
function generateMnemonic(seed) {
|
|
306766
307091
|
let h = 2166136261;
|
|
306767
307092
|
for (let i2 = 0; i2 < seed.length; i2++) {
|
|
@@ -306891,22 +307216,22 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
|
|
|
306891
307216
|
};
|
|
306892
307217
|
}
|
|
306893
307218
|
function saveBannerDesign(workDir, design) {
|
|
306894
|
-
const dir =
|
|
307219
|
+
const dir = join83(workDir, ".oa", "banners");
|
|
306895
307220
|
mkdirSync38(dir, { recursive: true });
|
|
306896
|
-
writeFileSync35(
|
|
307221
|
+
writeFileSync35(join83(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
|
|
306897
307222
|
}
|
|
306898
307223
|
function loadBannerDesign(workDir, id) {
|
|
306899
|
-
const file =
|
|
306900
|
-
if (!
|
|
307224
|
+
const file = join83(workDir, ".oa", "banners", `${id}.json`);
|
|
307225
|
+
if (!existsSync67(file)) return null;
|
|
306901
307226
|
try {
|
|
306902
|
-
return JSON.parse(
|
|
307227
|
+
return JSON.parse(readFileSync52(file, "utf8"));
|
|
306903
307228
|
} catch {
|
|
306904
307229
|
return null;
|
|
306905
307230
|
}
|
|
306906
307231
|
}
|
|
306907
307232
|
function listBannerDesigns(workDir) {
|
|
306908
|
-
const dir =
|
|
306909
|
-
if (!
|
|
307233
|
+
const dir = join83(workDir, ".oa", "banners");
|
|
307234
|
+
if (!existsSync67(dir)) return [];
|
|
306910
307235
|
try {
|
|
306911
307236
|
const { readdirSync: readdirSync31 } = __require("node:fs");
|
|
306912
307237
|
return readdirSync31(dir).filter((f2) => f2.endsWith(".json")).map((f2) => f2.replace(".json", ""));
|
|
@@ -307213,21 +307538,21 @@ var init_banner = __esm({
|
|
|
307213
307538
|
});
|
|
307214
307539
|
|
|
307215
307540
|
// packages/cli/src/tui/carousel-descriptors.ts
|
|
307216
|
-
import { existsSync as
|
|
307217
|
-
import { join as
|
|
307541
|
+
import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync36, mkdirSync as mkdirSync39, readdirSync as readdirSync19 } from "node:fs";
|
|
307542
|
+
import { join as join84, basename as basename14 } from "node:path";
|
|
307218
307543
|
function loadToolProfile(repoRoot) {
|
|
307219
|
-
const filePath =
|
|
307544
|
+
const filePath = join84(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
307220
307545
|
try {
|
|
307221
|
-
if (!
|
|
307222
|
-
return JSON.parse(
|
|
307546
|
+
if (!existsSync68(filePath)) return null;
|
|
307547
|
+
return JSON.parse(readFileSync53(filePath, "utf-8"));
|
|
307223
307548
|
} catch {
|
|
307224
307549
|
return null;
|
|
307225
307550
|
}
|
|
307226
307551
|
}
|
|
307227
307552
|
function saveToolProfile(repoRoot, profile) {
|
|
307228
|
-
const contextDir =
|
|
307553
|
+
const contextDir = join84(repoRoot, OA_DIR, "context");
|
|
307229
307554
|
mkdirSync39(contextDir, { recursive: true });
|
|
307230
|
-
writeFileSync36(
|
|
307555
|
+
writeFileSync36(join84(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
307231
307556
|
}
|
|
307232
307557
|
function categorizeToolCall(toolName) {
|
|
307233
307558
|
for (const cat2 of TOOL_CATEGORIES) {
|
|
@@ -307282,24 +307607,24 @@ function weightedColor(profile) {
|
|
|
307282
307607
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
307283
307608
|
}
|
|
307284
307609
|
function loadCachedDescriptors(repoRoot) {
|
|
307285
|
-
const filePath =
|
|
307610
|
+
const filePath = join84(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
307286
307611
|
try {
|
|
307287
|
-
if (!
|
|
307288
|
-
const cached = JSON.parse(
|
|
307612
|
+
if (!existsSync68(filePath)) return null;
|
|
307613
|
+
const cached = JSON.parse(readFileSync53(filePath, "utf-8"));
|
|
307289
307614
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
307290
307615
|
} catch {
|
|
307291
307616
|
return null;
|
|
307292
307617
|
}
|
|
307293
307618
|
}
|
|
307294
307619
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
307295
|
-
const contextDir =
|
|
307620
|
+
const contextDir = join84(repoRoot, OA_DIR, "context");
|
|
307296
307621
|
mkdirSync39(contextDir, { recursive: true });
|
|
307297
307622
|
const cached = {
|
|
307298
307623
|
phrases,
|
|
307299
307624
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
307300
307625
|
sourceHash
|
|
307301
307626
|
};
|
|
307302
|
-
writeFileSync36(
|
|
307627
|
+
writeFileSync36(join84(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
307303
307628
|
}
|
|
307304
307629
|
function generateDescriptors(repoRoot) {
|
|
307305
307630
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -307346,10 +307671,10 @@ function generateDescriptors(repoRoot) {
|
|
|
307346
307671
|
return phrases;
|
|
307347
307672
|
}
|
|
307348
307673
|
function extractFromPackageJson(repoRoot, tags) {
|
|
307349
|
-
const pkgPath =
|
|
307674
|
+
const pkgPath = join84(repoRoot, "package.json");
|
|
307350
307675
|
try {
|
|
307351
|
-
if (!
|
|
307352
|
-
const pkg = JSON.parse(
|
|
307676
|
+
if (!existsSync68(pkgPath)) return;
|
|
307677
|
+
const pkg = JSON.parse(readFileSync53(pkgPath, "utf-8"));
|
|
307353
307678
|
if (pkg.name && typeof pkg.name === "string") {
|
|
307354
307679
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
307355
307680
|
for (const p2 of parts) tags.push(p2);
|
|
@@ -307390,7 +307715,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
307390
307715
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
307391
307716
|
];
|
|
307392
307717
|
for (const check of manifestChecks) {
|
|
307393
|
-
if (
|
|
307718
|
+
if (existsSync68(join84(repoRoot, check.file))) {
|
|
307394
307719
|
tags.push(check.tag);
|
|
307395
307720
|
}
|
|
307396
307721
|
}
|
|
@@ -307412,15 +307737,15 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
307412
307737
|
}
|
|
307413
307738
|
}
|
|
307414
307739
|
function extractFromMemory(repoRoot, tags) {
|
|
307415
|
-
const memoryDir =
|
|
307740
|
+
const memoryDir = join84(repoRoot, OA_DIR, "memory");
|
|
307416
307741
|
try {
|
|
307417
|
-
if (!
|
|
307742
|
+
if (!existsSync68(memoryDir)) return;
|
|
307418
307743
|
const files = readdirSync19(memoryDir).filter((f2) => f2.endsWith(".json"));
|
|
307419
307744
|
for (const file of files) {
|
|
307420
307745
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
307421
307746
|
tags.push(topic);
|
|
307422
307747
|
try {
|
|
307423
|
-
const data = JSON.parse(
|
|
307748
|
+
const data = JSON.parse(readFileSync53(join84(memoryDir, file), "utf-8"));
|
|
307424
307749
|
if (data && typeof data === "object") {
|
|
307425
307750
|
const keys = Object.keys(data).slice(0, 3);
|
|
307426
307751
|
for (const key of keys) {
|
|
@@ -308115,10 +308440,10 @@ var init_stream_renderer = __esm({
|
|
|
308115
308440
|
|
|
308116
308441
|
// packages/cli/src/tui/edit-history.ts
|
|
308117
308442
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync40 } from "node:fs";
|
|
308118
|
-
import { join as
|
|
308443
|
+
import { join as join85 } from "node:path";
|
|
308119
308444
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
308120
|
-
const historyDir =
|
|
308121
|
-
const logPath2 =
|
|
308445
|
+
const historyDir = join85(repoRoot, ".oa", "history");
|
|
308446
|
+
const logPath2 = join85(historyDir, "edits.jsonl");
|
|
308122
308447
|
try {
|
|
308123
308448
|
mkdirSync40(historyDir, { recursive: true });
|
|
308124
308449
|
} catch {
|
|
@@ -308228,17 +308553,17 @@ var init_edit_history = __esm({
|
|
|
308228
308553
|
});
|
|
308229
308554
|
|
|
308230
308555
|
// packages/cli/src/tui/promptLoader.ts
|
|
308231
|
-
import { readFileSync as
|
|
308232
|
-
import { join as
|
|
308556
|
+
import { readFileSync as readFileSync54, existsSync as existsSync69 } from "node:fs";
|
|
308557
|
+
import { join as join86, dirname as dirname24 } from "node:path";
|
|
308233
308558
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
308234
308559
|
function loadPrompt3(promptPath, vars) {
|
|
308235
308560
|
let content = cache6.get(promptPath);
|
|
308236
308561
|
if (content === void 0) {
|
|
308237
|
-
const fullPath =
|
|
308238
|
-
if (!
|
|
308562
|
+
const fullPath = join86(PROMPTS_DIR3, promptPath);
|
|
308563
|
+
if (!existsSync69(fullPath)) {
|
|
308239
308564
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
308240
308565
|
}
|
|
308241
|
-
content =
|
|
308566
|
+
content = readFileSync54(fullPath, "utf-8");
|
|
308242
308567
|
cache6.set(promptPath, content);
|
|
308243
308568
|
}
|
|
308244
308569
|
if (!vars) return content;
|
|
@@ -308250,16 +308575,16 @@ var init_promptLoader3 = __esm({
|
|
|
308250
308575
|
"use strict";
|
|
308251
308576
|
__filename5 = fileURLToPath14(import.meta.url);
|
|
308252
308577
|
__dirname7 = dirname24(__filename5);
|
|
308253
|
-
devPath2 =
|
|
308254
|
-
publishedPath2 =
|
|
308255
|
-
PROMPTS_DIR3 =
|
|
308578
|
+
devPath2 = join86(__dirname7, "..", "..", "prompts");
|
|
308579
|
+
publishedPath2 = join86(__dirname7, "..", "prompts");
|
|
308580
|
+
PROMPTS_DIR3 = existsSync69(devPath2) ? devPath2 : publishedPath2;
|
|
308256
308581
|
cache6 = /* @__PURE__ */ new Map();
|
|
308257
308582
|
}
|
|
308258
308583
|
});
|
|
308259
308584
|
|
|
308260
308585
|
// packages/cli/src/tui/dream-engine.ts
|
|
308261
|
-
import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync37, readFileSync as
|
|
308262
|
-
import { join as
|
|
308586
|
+
import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync37, readFileSync as readFileSync55, existsSync as existsSync70, readdirSync as readdirSync20 } from "node:fs";
|
|
308587
|
+
import { join as join87, basename as basename15 } from "node:path";
|
|
308263
308588
|
import { execSync as execSync52 } from "node:child_process";
|
|
308264
308589
|
function setDreamWriteContent(fn) {
|
|
308265
308590
|
_dreamWriteContent = fn;
|
|
@@ -308272,10 +308597,10 @@ function dreamWrite(fn) {
|
|
|
308272
308597
|
}
|
|
308273
308598
|
}
|
|
308274
308599
|
function loadAutoresearchMemory(repoRoot) {
|
|
308275
|
-
const memoryPath =
|
|
308276
|
-
if (!
|
|
308600
|
+
const memoryPath = join87(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
308601
|
+
if (!existsSync70(memoryPath)) return "";
|
|
308277
308602
|
try {
|
|
308278
|
-
const raw =
|
|
308603
|
+
const raw = readFileSync55(memoryPath, "utf-8");
|
|
308279
308604
|
const data = JSON.parse(raw);
|
|
308280
308605
|
const sections = [];
|
|
308281
308606
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -308471,12 +308796,12 @@ var init_dream_engine = __esm({
|
|
|
308471
308796
|
const rawPath = String(args["path"] ?? "");
|
|
308472
308797
|
const content = String(args["content"] ?? "");
|
|
308473
308798
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
308474
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
308799
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join87(this.autoresearchDir, basename15(rawPath)) : join87(this.autoresearchDir, rawPath);
|
|
308475
308800
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
308476
308801
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
|
|
308477
308802
|
}
|
|
308478
308803
|
try {
|
|
308479
|
-
const dir =
|
|
308804
|
+
const dir = join87(targetPath, "..");
|
|
308480
308805
|
mkdirSync41(dir, { recursive: true });
|
|
308481
308806
|
writeFileSync37(targetPath, content, "utf-8");
|
|
308482
308807
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
|
|
@@ -308505,15 +308830,15 @@ var init_dream_engine = __esm({
|
|
|
308505
308830
|
const rawPath = String(args["path"] ?? "");
|
|
308506
308831
|
const oldStr = String(args["old_string"] ?? "");
|
|
308507
308832
|
const newStr = String(args["new_string"] ?? "");
|
|
308508
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
308833
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join87(this.autoresearchDir, basename15(rawPath)) : join87(this.autoresearchDir, rawPath);
|
|
308509
308834
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
308510
308835
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
|
|
308511
308836
|
}
|
|
308512
308837
|
try {
|
|
308513
|
-
if (!
|
|
308838
|
+
if (!existsSync70(targetPath)) {
|
|
308514
308839
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
|
|
308515
308840
|
}
|
|
308516
|
-
let content =
|
|
308841
|
+
let content = readFileSync55(targetPath, "utf-8");
|
|
308517
308842
|
if (!content.includes(oldStr)) {
|
|
308518
308843
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
|
|
308519
308844
|
}
|
|
@@ -308557,12 +308882,12 @@ var init_dream_engine = __esm({
|
|
|
308557
308882
|
const rawPath = String(args["path"] ?? "");
|
|
308558
308883
|
const content = String(args["content"] ?? "");
|
|
308559
308884
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
308560
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
308885
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join87(this.dreamsDir, basename15(rawPath)) : join87(this.dreamsDir, rawPath);
|
|
308561
308886
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
308562
308887
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start2 };
|
|
308563
308888
|
}
|
|
308564
308889
|
try {
|
|
308565
|
-
const dir =
|
|
308890
|
+
const dir = join87(targetPath, "..");
|
|
308566
308891
|
mkdirSync41(dir, { recursive: true });
|
|
308567
308892
|
writeFileSync37(targetPath, content, "utf-8");
|
|
308568
308893
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
|
|
@@ -308591,15 +308916,15 @@ var init_dream_engine = __esm({
|
|
|
308591
308916
|
const rawPath = String(args["path"] ?? "");
|
|
308592
308917
|
const oldStr = String(args["old_string"] ?? "");
|
|
308593
308918
|
const newStr = String(args["new_string"] ?? "");
|
|
308594
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
308919
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join87(this.dreamsDir, basename15(rawPath)) : join87(this.dreamsDir, rawPath);
|
|
308595
308920
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
308596
308921
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start2 };
|
|
308597
308922
|
}
|
|
308598
308923
|
try {
|
|
308599
|
-
if (!
|
|
308924
|
+
if (!existsSync70(targetPath)) {
|
|
308600
308925
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
|
|
308601
308926
|
}
|
|
308602
|
-
let content =
|
|
308927
|
+
let content = readFileSync55(targetPath, "utf-8");
|
|
308603
308928
|
if (!content.includes(oldStr)) {
|
|
308604
308929
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
|
|
308605
308930
|
}
|
|
@@ -308652,7 +308977,7 @@ var init_dream_engine = __esm({
|
|
|
308652
308977
|
constructor(config, repoRoot) {
|
|
308653
308978
|
this.config = config;
|
|
308654
308979
|
this.repoRoot = repoRoot;
|
|
308655
|
-
this.dreamsDir =
|
|
308980
|
+
this.dreamsDir = join87(repoRoot, ".oa", "dreams");
|
|
308656
308981
|
this.state = {
|
|
308657
308982
|
mode: "default",
|
|
308658
308983
|
active: false,
|
|
@@ -308761,7 +309086,7 @@ ${result.summary}`;
|
|
|
308761
309086
|
if (mode !== "default" || cycle === totalCycles) {
|
|
308762
309087
|
renderDreamContraction(cycle);
|
|
308763
309088
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
308764
|
-
const summaryPath =
|
|
309089
|
+
const summaryPath = join87(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
308765
309090
|
writeFileSync37(summaryPath, cycleSummary, "utf-8");
|
|
308766
309091
|
}
|
|
308767
309092
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -309001,7 +309326,7 @@ After synthesis, call task_complete with the final prioritized summary.`,
|
|
|
309001
309326
|
}
|
|
309002
309327
|
/** Build role-specific tool sets for swarm agents */
|
|
309003
309328
|
buildSwarmTools(role, _workspace) {
|
|
309004
|
-
const autoresearchDir =
|
|
309329
|
+
const autoresearchDir = join87(this.repoRoot, ".oa", "autoresearch");
|
|
309005
309330
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
309006
309331
|
switch (role) {
|
|
309007
309332
|
case "researcher": {
|
|
@@ -309400,7 +309725,7 @@ Call task_complete with a human-readable summary of the autoresearch session.`,
|
|
|
309400
309725
|
workspace,
|
|
309401
309726
|
onEvent
|
|
309402
309727
|
);
|
|
309403
|
-
const reportPath =
|
|
309728
|
+
const reportPath = join87(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
309404
309729
|
const report = `# Autoresearch Swarm Report — Cycle ${cycleNum}
|
|
309405
309730
|
|
|
309406
309731
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -309489,7 +309814,7 @@ ${summaryResult}
|
|
|
309489
309814
|
}
|
|
309490
309815
|
/** Save workspace backup for lucid mode */
|
|
309491
309816
|
saveVersionCheckpoint(cycle) {
|
|
309492
|
-
const checkpointDir =
|
|
309817
|
+
const checkpointDir = join87(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
309493
309818
|
try {
|
|
309494
309819
|
mkdirSync41(checkpointDir, { recursive: true });
|
|
309495
309820
|
try {
|
|
@@ -309508,11 +309833,11 @@ ${summaryResult}
|
|
|
309508
309833
|
encoding: "utf-8",
|
|
309509
309834
|
timeout: 5e3
|
|
309510
309835
|
}).trim();
|
|
309511
|
-
writeFileSync37(
|
|
309512
|
-
writeFileSync37(
|
|
309513
|
-
writeFileSync37(
|
|
309836
|
+
writeFileSync37(join87(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
309837
|
+
writeFileSync37(join87(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
309838
|
+
writeFileSync37(join87(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
309514
309839
|
writeFileSync37(
|
|
309515
|
-
|
|
309840
|
+
join87(checkpointDir, "checkpoint.json"),
|
|
309516
309841
|
JSON.stringify({
|
|
309517
309842
|
cycle,
|
|
309518
309843
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -309524,7 +309849,7 @@ ${summaryResult}
|
|
|
309524
309849
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
309525
309850
|
} catch {
|
|
309526
309851
|
writeFileSync37(
|
|
309527
|
-
|
|
309852
|
+
join87(checkpointDir, "checkpoint.json"),
|
|
309528
309853
|
JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2),
|
|
309529
309854
|
"utf-8"
|
|
309530
309855
|
);
|
|
@@ -309585,7 +309910,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309585
309910
|
---
|
|
309586
309911
|
*Auto-generated by open-agents dream engine*
|
|
309587
309912
|
`;
|
|
309588
|
-
writeFileSync37(
|
|
309913
|
+
writeFileSync37(join87(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
309589
309914
|
} catch {
|
|
309590
309915
|
}
|
|
309591
309916
|
}
|
|
@@ -309606,7 +309931,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309606
309931
|
results: []
|
|
309607
309932
|
};
|
|
309608
309933
|
renderInfo("Memory consolidation starting — Phase 1: Orient → Phase 2: Gather → Phase 3: Consolidate → Phase 4: Prune");
|
|
309609
|
-
const memoryDir =
|
|
309934
|
+
const memoryDir = join87(this.repoRoot, ".oa", "memory");
|
|
309610
309935
|
mkdirSync41(memoryDir, { recursive: true });
|
|
309611
309936
|
let prompt;
|
|
309612
309937
|
try {
|
|
@@ -309672,7 +309997,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309672
309997
|
});
|
|
309673
309998
|
try {
|
|
309674
309999
|
writeFileSync37(
|
|
309675
|
-
|
|
310000
|
+
join87(memoryDir, ".last-consolidation"),
|
|
309676
310001
|
JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), summary: result.summary?.slice(0, 500) }) + "\n"
|
|
309677
310002
|
);
|
|
309678
310003
|
} catch {
|
|
@@ -309690,7 +310015,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309690
310015
|
saveDreamState() {
|
|
309691
310016
|
try {
|
|
309692
310017
|
writeFileSync37(
|
|
309693
|
-
|
|
310018
|
+
join87(this.dreamsDir, "dream-state.json"),
|
|
309694
310019
|
JSON.stringify(this.state, null, 2) + "\n",
|
|
309695
310020
|
"utf-8"
|
|
309696
310021
|
);
|
|
@@ -310060,8 +310385,8 @@ var init_bless_engine = __esm({
|
|
|
310060
310385
|
});
|
|
310061
310386
|
|
|
310062
310387
|
// packages/cli/src/tui/dmn-engine.ts
|
|
310063
|
-
import { existsSync as
|
|
310064
|
-
import { join as
|
|
310388
|
+
import { existsSync as existsSync71, readFileSync as readFileSync56, writeFileSync as writeFileSync38, mkdirSync as mkdirSync42, readdirSync as readdirSync21, unlinkSync as unlinkSync18 } from "node:fs";
|
|
310389
|
+
import { join as join88, basename as basename16 } from "node:path";
|
|
310065
310390
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
310066
310391
|
const competenceReport = competence.length > 0 ? competence.map((c7) => {
|
|
310067
310392
|
const rate = c7.attempts > 0 ? Math.round(c7.successes / c7.attempts * 100) : 0;
|
|
@@ -310166,8 +310491,8 @@ var init_dmn_engine = __esm({
|
|
|
310166
310491
|
constructor(config, repoRoot) {
|
|
310167
310492
|
this.config = config;
|
|
310168
310493
|
this.repoRoot = repoRoot;
|
|
310169
|
-
this.stateDir =
|
|
310170
|
-
this.historyDir =
|
|
310494
|
+
this.stateDir = join88(repoRoot, ".oa", "dmn");
|
|
310495
|
+
this.historyDir = join88(repoRoot, ".oa", "dmn", "cycles");
|
|
310171
310496
|
mkdirSync42(this.historyDir, { recursive: true });
|
|
310172
310497
|
this.loadState();
|
|
310173
310498
|
}
|
|
@@ -310802,11 +311127,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310802
311127
|
async gatherMemoryTopics() {
|
|
310803
311128
|
const topics = [];
|
|
310804
311129
|
const dirs = [
|
|
310805
|
-
|
|
310806
|
-
|
|
311130
|
+
join88(this.repoRoot, ".oa", "memory"),
|
|
311131
|
+
join88(this.repoRoot, ".open-agents", "memory")
|
|
310807
311132
|
];
|
|
310808
311133
|
for (const dir of dirs) {
|
|
310809
|
-
if (!
|
|
311134
|
+
if (!existsSync71(dir)) continue;
|
|
310810
311135
|
try {
|
|
310811
311136
|
const files = readdirSync21(dir).filter((f2) => f2.endsWith(".json"));
|
|
310812
311137
|
for (const f2 of files) {
|
|
@@ -310820,10 +311145,10 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310820
311145
|
}
|
|
310821
311146
|
// ── State persistence ─────────────────────────────────────────────────
|
|
310822
311147
|
loadState() {
|
|
310823
|
-
const path5 =
|
|
310824
|
-
if (
|
|
311148
|
+
const path5 = join88(this.stateDir, "state.json");
|
|
311149
|
+
if (existsSync71(path5)) {
|
|
310825
311150
|
try {
|
|
310826
|
-
this.state = JSON.parse(
|
|
311151
|
+
this.state = JSON.parse(readFileSync56(path5, "utf-8"));
|
|
310827
311152
|
} catch {
|
|
310828
311153
|
}
|
|
310829
311154
|
}
|
|
@@ -310831,7 +311156,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310831
311156
|
saveState() {
|
|
310832
311157
|
try {
|
|
310833
311158
|
writeFileSync38(
|
|
310834
|
-
|
|
311159
|
+
join88(this.stateDir, "state.json"),
|
|
310835
311160
|
JSON.stringify(this.state, null, 2) + "\n",
|
|
310836
311161
|
"utf-8"
|
|
310837
311162
|
);
|
|
@@ -310842,7 +311167,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310842
311167
|
try {
|
|
310843
311168
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
310844
311169
|
writeFileSync38(
|
|
310845
|
-
|
|
311170
|
+
join88(this.historyDir, filename),
|
|
310846
311171
|
JSON.stringify(result, null, 2) + "\n",
|
|
310847
311172
|
"utf-8"
|
|
310848
311173
|
);
|
|
@@ -310850,7 +311175,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310850
311175
|
if (files.length > 50) {
|
|
310851
311176
|
for (const old of files.slice(0, files.length - 50)) {
|
|
310852
311177
|
try {
|
|
310853
|
-
unlinkSync18(
|
|
311178
|
+
unlinkSync18(join88(this.historyDir, old));
|
|
310854
311179
|
} catch {
|
|
310855
311180
|
}
|
|
310856
311181
|
}
|
|
@@ -310863,8 +311188,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310863
311188
|
});
|
|
310864
311189
|
|
|
310865
311190
|
// packages/cli/src/tui/snr-engine.ts
|
|
310866
|
-
import { existsSync as
|
|
310867
|
-
import { join as
|
|
311191
|
+
import { existsSync as existsSync72, readdirSync as readdirSync22, readFileSync as readFileSync57 } from "node:fs";
|
|
311192
|
+
import { join as join89, basename as basename17 } from "node:path";
|
|
310868
311193
|
function computeDPrime(signalScores, noiseScores) {
|
|
310869
311194
|
if (signalScores.length === 0 || noiseScores.length === 0) return 0;
|
|
310870
311195
|
const mean = (arr) => arr.reduce((s2, v) => s2 + v, 0) / arr.length;
|
|
@@ -311148,18 +311473,18 @@ Call task_complete with the JSON array when done.`,
|
|
|
311148
311473
|
loadMemoryEntries(topics) {
|
|
311149
311474
|
const entries = [];
|
|
311150
311475
|
const dirs = [
|
|
311151
|
-
|
|
311152
|
-
|
|
311476
|
+
join89(this.repoRoot, ".oa", "memory"),
|
|
311477
|
+
join89(this.repoRoot, ".open-agents", "memory")
|
|
311153
311478
|
];
|
|
311154
311479
|
for (const dir of dirs) {
|
|
311155
|
-
if (!
|
|
311480
|
+
if (!existsSync72(dir)) continue;
|
|
311156
311481
|
try {
|
|
311157
311482
|
const files = readdirSync22(dir).filter((f2) => f2.endsWith(".json"));
|
|
311158
311483
|
for (const f2 of files) {
|
|
311159
311484
|
const topic = basename17(f2, ".json");
|
|
311160
311485
|
if (topics.length > 0 && !topics.includes(topic)) continue;
|
|
311161
311486
|
try {
|
|
311162
|
-
const data = JSON.parse(
|
|
311487
|
+
const data = JSON.parse(readFileSync57(join89(dir, f2), "utf-8"));
|
|
311163
311488
|
for (const [key, val] of Object.entries(data)) {
|
|
311164
311489
|
const value2 = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
311165
311490
|
entries.push({ topic, key, value: value2 });
|
|
@@ -311704,7 +312029,7 @@ var init_tool_policy = __esm({
|
|
|
311704
312029
|
|
|
311705
312030
|
// packages/cli/src/tui/telegram-bridge.ts
|
|
311706
312031
|
import { mkdirSync as mkdirSync43, unlinkSync as unlinkSync19 } from "node:fs";
|
|
311707
|
-
import { join as
|
|
312032
|
+
import { join as join90, resolve as resolve32 } from "node:path";
|
|
311708
312033
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
311709
312034
|
function convertMarkdownToTelegramHTML(md) {
|
|
311710
312035
|
let html = md;
|
|
@@ -312460,7 +312785,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
312460
312785
|
if (!res.ok) return null;
|
|
312461
312786
|
const buffer2 = Buffer.from(await res.arrayBuffer());
|
|
312462
312787
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension2}`;
|
|
312463
|
-
const localPath =
|
|
312788
|
+
const localPath = join90(this.mediaCacheDir, fileName);
|
|
312464
312789
|
await writeFileAsync(localPath, buffer2);
|
|
312465
312790
|
return localPath;
|
|
312466
312791
|
} catch {
|
|
@@ -312880,192 +313205,6 @@ var init_task_manager_singleton = __esm({
|
|
|
312880
313205
|
}
|
|
312881
313206
|
});
|
|
312882
313207
|
|
|
312883
|
-
// packages/cli/src/tui/tui-tasks-renderer.ts
|
|
312884
|
-
import { existsSync as existsSync73, readFileSync as readFileSync57, watch as fsWatch2 } from "node:fs";
|
|
312885
|
-
import { join as join90 } from "node:path";
|
|
312886
|
-
import { homedir as homedir30 } from "node:os";
|
|
312887
|
-
function todoDir2() {
|
|
312888
|
-
return join90(homedir30(), ".open-agents", "todos");
|
|
312889
|
-
}
|
|
312890
|
-
function todoPath2(sessionId) {
|
|
312891
|
-
const safe = sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
312892
|
-
return join90(todoDir2(), `${safe}.json`);
|
|
312893
|
-
}
|
|
312894
|
-
function setTuiTasksSession(sessionId) {
|
|
312895
|
-
if (sessionId === _activeSessionId) return;
|
|
312896
|
-
_activeSessionId = sessionId || null;
|
|
312897
|
-
if (_watcher) {
|
|
312898
|
-
try {
|
|
312899
|
-
_watcher.close();
|
|
312900
|
-
} catch {
|
|
312901
|
-
}
|
|
312902
|
-
_watcher = null;
|
|
312903
|
-
}
|
|
312904
|
-
if (!_activeSessionId) {
|
|
312905
|
-
_lastTodos = [];
|
|
312906
|
-
applyHeightChange(0);
|
|
312907
|
-
return;
|
|
312908
|
-
}
|
|
312909
|
-
loadTodos();
|
|
312910
|
-
installWatcher();
|
|
312911
|
-
scheduleRedraw();
|
|
312912
|
-
}
|
|
312913
|
-
function onTuiTasksHeightChange(cb) {
|
|
312914
|
-
_onResizeChange = cb;
|
|
312915
|
-
}
|
|
312916
|
-
function refreshTuiTasks() {
|
|
312917
|
-
if (!_activeSessionId) return;
|
|
312918
|
-
loadTodos();
|
|
312919
|
-
scheduleRedraw();
|
|
312920
|
-
}
|
|
312921
|
-
function teardownTuiTasks() {
|
|
312922
|
-
if (_watcher) {
|
|
312923
|
-
try {
|
|
312924
|
-
_watcher.close();
|
|
312925
|
-
} catch {
|
|
312926
|
-
}
|
|
312927
|
-
_watcher = null;
|
|
312928
|
-
}
|
|
312929
|
-
_activeSessionId = null;
|
|
312930
|
-
_lastTodos = [];
|
|
312931
|
-
applyHeightChange(0);
|
|
312932
|
-
}
|
|
312933
|
-
function installWatcher() {
|
|
312934
|
-
if (!_activeSessionId) return;
|
|
312935
|
-
try {
|
|
312936
|
-
_watcher = fsWatch2(todoDir2(), { persistent: false }, (_evt, fname) => {
|
|
312937
|
-
if (!fname || !_activeSessionId) return;
|
|
312938
|
-
const expected = `${_activeSessionId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
|
|
312939
|
-
if (fname !== expected) return;
|
|
312940
|
-
loadTodos();
|
|
312941
|
-
scheduleRedraw();
|
|
312942
|
-
});
|
|
312943
|
-
} catch {
|
|
312944
|
-
}
|
|
312945
|
-
}
|
|
312946
|
-
function loadTodos() {
|
|
312947
|
-
if (!_activeSessionId) {
|
|
312948
|
-
_lastTodos = [];
|
|
312949
|
-
return;
|
|
312950
|
-
}
|
|
312951
|
-
try {
|
|
312952
|
-
const fp = todoPath2(_activeSessionId);
|
|
312953
|
-
if (!existsSync73(fp)) {
|
|
312954
|
-
_lastTodos = [];
|
|
312955
|
-
return;
|
|
312956
|
-
}
|
|
312957
|
-
const parsed = JSON.parse(readFileSync57(fp, "utf-8"));
|
|
312958
|
-
_lastTodos = Array.isArray(parsed) ? parsed : [];
|
|
312959
|
-
} catch {
|
|
312960
|
-
_lastTodos = [];
|
|
312961
|
-
}
|
|
312962
|
-
}
|
|
312963
|
-
function scheduleRedraw() {
|
|
312964
|
-
if (_redrawScheduled || !_enabled) return;
|
|
312965
|
-
_redrawScheduled = true;
|
|
312966
|
-
setImmediate(() => {
|
|
312967
|
-
_redrawScheduled = false;
|
|
312968
|
-
render();
|
|
312969
|
-
});
|
|
312970
|
-
}
|
|
312971
|
-
function computeTargetHeight() {
|
|
312972
|
-
if (!_lastTodos || _lastTodos.length === 0) return 0;
|
|
312973
|
-
const itemRows = Math.min(_lastTodos.length, MAX_VISIBLE_ROWS - 1);
|
|
312974
|
-
return 1 + itemRows;
|
|
312975
|
-
}
|
|
312976
|
-
function applyHeightChange(nextHeight) {
|
|
312977
|
-
const changed = setTasksHeight(nextHeight);
|
|
312978
|
-
if (changed) {
|
|
312979
|
-
notifyLayoutResize();
|
|
312980
|
-
}
|
|
312981
|
-
if (_onResizeChange) {
|
|
312982
|
-
try {
|
|
312983
|
-
_onResizeChange(nextHeight);
|
|
312984
|
-
} catch {
|
|
312985
|
-
}
|
|
312986
|
-
}
|
|
312987
|
-
}
|
|
312988
|
-
function statusToAnsi(status) {
|
|
312989
|
-
switch (status) {
|
|
312990
|
-
case "completed":
|
|
312991
|
-
return { mark: "◉", color: MUTED_GREEN, box: GREEN };
|
|
312992
|
-
case "in_progress":
|
|
312993
|
-
return { mark: "◐", color: GOLD, box: GOLD };
|
|
312994
|
-
case "blocked":
|
|
312995
|
-
return { mark: "◍", color: RED, box: RED };
|
|
312996
|
-
default:
|
|
312997
|
-
return { mark: "〇", color: GREY, box: GREY };
|
|
312998
|
-
}
|
|
312999
|
-
}
|
|
313000
|
-
function truncate2(s2, max) {
|
|
313001
|
-
if (s2.length <= max) return s2.padEnd(max, " ");
|
|
313002
|
-
return s2.slice(0, Math.max(0, max - 1)) + "…";
|
|
313003
|
-
}
|
|
313004
|
-
function render() {
|
|
313005
|
-
if (!_enabled) return;
|
|
313006
|
-
const target = computeTargetHeight();
|
|
313007
|
-
applyHeightChange(target);
|
|
313008
|
-
if (target === 0) return;
|
|
313009
|
-
const L = layout();
|
|
313010
|
-
const cols = Math.max(20, termCols());
|
|
313011
|
-
const completed = _lastTodos.filter((t2) => t2.status === "completed").length;
|
|
313012
|
-
const total = _lastTodos.length;
|
|
313013
|
-
const headerColor = completed === total ? GREEN : GOLD;
|
|
313014
|
-
const lines = [];
|
|
313015
|
-
const headerText = `tasks ${headerColor}${completed}/${total}${RESET2}${DIM_LABEL} (todo_write)${RESET2}`;
|
|
313016
|
-
lines.push(headerText);
|
|
313017
|
-
const visible = _lastTodos.slice(0, MAX_VISIBLE_ROWS - 1);
|
|
313018
|
-
for (const t2 of visible) {
|
|
313019
|
-
const { mark, color } = statusToAnsi(t2.status);
|
|
313020
|
-
const contentWidth = Math.max(4, cols - 8);
|
|
313021
|
-
const contentText = t2.content + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
|
|
313022
|
-
const truncated = truncate2(contentText, contentWidth);
|
|
313023
|
-
lines.push(`${color}${mark}${RESET2} ${color}${truncated}${RESET2}`);
|
|
313024
|
-
}
|
|
313025
|
-
if (_lastTodos.length > visible.length) {
|
|
313026
|
-
const more = _lastTodos.length - visible.length;
|
|
313027
|
-
lines[lines.length - 1] = `${DIM_LABEL}… +${more} more${RESET2}`;
|
|
313028
|
-
}
|
|
313029
|
-
let out = HIDE + SAVE;
|
|
313030
|
-
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
313031
|
-
const row = L.tasksTop + i2;
|
|
313032
|
-
if (row > L.tasksBottom) break;
|
|
313033
|
-
out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET2}`;
|
|
313034
|
-
}
|
|
313035
|
-
out += RESTORE + SHOW;
|
|
313036
|
-
try {
|
|
313037
|
-
process.stdout.write(out);
|
|
313038
|
-
} catch {
|
|
313039
|
-
}
|
|
313040
|
-
}
|
|
313041
|
-
var _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET2, BG, DIM_LABEL, GOLD, GREEN, MUTED_GREEN, GREY, RED;
|
|
313042
|
-
var init_tui_tasks_renderer = __esm({
|
|
313043
|
-
"packages/cli/src/tui/tui-tasks-renderer.ts"() {
|
|
313044
|
-
"use strict";
|
|
313045
|
-
init_layout2();
|
|
313046
|
-
_activeSessionId = null;
|
|
313047
|
-
_watcher = null;
|
|
313048
|
-
_lastTodos = [];
|
|
313049
|
-
_enabled = true;
|
|
313050
|
-
_redrawScheduled = false;
|
|
313051
|
-
_onResizeChange = null;
|
|
313052
|
-
MAX_VISIBLE_ROWS = 8;
|
|
313053
|
-
SAVE = "\x1B[s";
|
|
313054
|
-
RESTORE = "\x1B[u";
|
|
313055
|
-
HIDE = "\x1B[?25l";
|
|
313056
|
-
SHOW = "\x1B[?25h";
|
|
313057
|
-
CLEAR_LINE = "\x1B[2K";
|
|
313058
|
-
RESET2 = "\x1B[0m";
|
|
313059
|
-
BG = "\x1B[48;2;23;23;26m";
|
|
313060
|
-
DIM_LABEL = "\x1B[38;2;68;68;68m";
|
|
313061
|
-
GOLD = "\x1B[38;2;178;146;10m";
|
|
313062
|
-
GREEN = "\x1B[38;2;95;165;95m";
|
|
313063
|
-
MUTED_GREEN = "\x1B[38;2;74;122;74m";
|
|
313064
|
-
GREY = "\x1B[38;2;102;102;102m";
|
|
313065
|
-
RED = "\x1B[38;2;178;95;95m";
|
|
313066
|
-
}
|
|
313067
|
-
});
|
|
313068
|
-
|
|
313069
313208
|
// packages/cli/src/tui/mouse-filter.ts
|
|
313070
313209
|
var mouse_filter_exports = {};
|
|
313071
313210
|
__export(mouse_filter_exports, {
|
|
@@ -326283,6 +326422,12 @@ async function startInteractive(config, repoPath) {
|
|
|
326283
326422
|
} catch {
|
|
326284
326423
|
}
|
|
326285
326424
|
});
|
|
326425
|
+
statusBar.setOnResizeFinalized(() => {
|
|
326426
|
+
try {
|
|
326427
|
+
refreshTuiTasksSync();
|
|
326428
|
+
} catch {
|
|
326429
|
+
}
|
|
326430
|
+
});
|
|
326286
326431
|
if (process.stdout.isTTY) {
|
|
326287
326432
|
const scrollTop = carouselLines > 0 ? carouselLines : 1;
|
|
326288
326433
|
statusBar.activate(scrollTop);
|
|
@@ -326503,8 +326648,18 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
|
|
|
326503
326648
|
banner.setFocused(focused);
|
|
326504
326649
|
banner.renderCurrentFrame();
|
|
326505
326650
|
});
|
|
326506
|
-
const { onOverlayLeave: onOverlayLeave2 } = await Promise.resolve().then(() => (init_overlay_lock(), overlay_lock_exports));
|
|
326651
|
+
const { onOverlayLeave: onOverlayLeave2, onOverlayEnter: onOverlayEnter2 } = await Promise.resolve().then(() => (init_overlay_lock(), overlay_lock_exports));
|
|
326652
|
+
onOverlayEnter2(() => {
|
|
326653
|
+
try {
|
|
326654
|
+
setTuiTasksScope({ overlayActive: true });
|
|
326655
|
+
} catch {
|
|
326656
|
+
}
|
|
326657
|
+
});
|
|
326507
326658
|
onOverlayLeave2(() => {
|
|
326659
|
+
try {
|
|
326660
|
+
setTuiTasksScope({ overlayActive: false });
|
|
326661
|
+
} catch {
|
|
326662
|
+
}
|
|
326508
326663
|
statusBar.suspendContentLayer();
|
|
326509
326664
|
banner.renderCurrentFrame();
|
|
326510
326665
|
statusBar.resumeContentLayer();
|
|
@@ -326513,6 +326668,10 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
|
|
|
326513
326668
|
if (statusBar.isActive) {
|
|
326514
326669
|
statusBar.refreshDisplay();
|
|
326515
326670
|
}
|
|
326671
|
+
try {
|
|
326672
|
+
refreshTuiTasks();
|
|
326673
|
+
} catch {
|
|
326674
|
+
}
|
|
326516
326675
|
});
|
|
326517
326676
|
if (cohereEnabled) {
|
|
326518
326677
|
statusBar.setCohereActive(true);
|
|
@@ -327041,10 +327200,6 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
327041
327200
|
process.stdout.on("resize", () => {
|
|
327042
327201
|
statusBar.handleResize();
|
|
327043
327202
|
setTermSize(process.stdout.rows ?? 24, process.stdout.columns ?? 80);
|
|
327044
|
-
try {
|
|
327045
|
-
refreshTuiTasks();
|
|
327046
|
-
} catch {
|
|
327047
|
-
}
|
|
327048
327203
|
if (isNeovimActive()) {
|
|
327049
327204
|
const contentRows = statusBar.isActive ? statusBar.availableContentRows : Math.max(5, termRows() - 6);
|
|
327050
327205
|
resizeNeovim(termCols(), contentRows);
|