open-agents-ai 0.187.211 → 0.187.212
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 +730 -634
- 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,249 @@ 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
|
+
setTuiTasksEnabled: () => setTuiTasksEnabled,
|
|
288490
|
+
setTuiTasksScope: () => setTuiTasksScope,
|
|
288491
|
+
setTuiTasksSession: () => setTuiTasksSession,
|
|
288492
|
+
teardownTuiTasks: () => teardownTuiTasks
|
|
288493
|
+
});
|
|
288494
|
+
import { existsSync as existsSync57, readFileSync as readFileSync43, watch as fsWatch2 } from "node:fs";
|
|
288495
|
+
import { join as join74 } from "node:path";
|
|
288496
|
+
import { homedir as homedir24 } from "node:os";
|
|
288497
|
+
function panelEffectivelyVisible() {
|
|
288498
|
+
return _enabled && !_scopeOverlayActive && !_scopeNeovimActive && _scopeMainViewActive;
|
|
288499
|
+
}
|
|
288500
|
+
function todoDir2() {
|
|
288501
|
+
return join74(homedir24(), ".open-agents", "todos");
|
|
288502
|
+
}
|
|
288503
|
+
function todoPath2(sessionId) {
|
|
288504
|
+
const safe = sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
288505
|
+
return join74(todoDir2(), `${safe}.json`);
|
|
288506
|
+
}
|
|
288507
|
+
function setTuiTasksSession(sessionId) {
|
|
288508
|
+
if (sessionId === _activeSessionId) return;
|
|
288509
|
+
_activeSessionId = sessionId || null;
|
|
288510
|
+
if (_watcher) {
|
|
288511
|
+
try {
|
|
288512
|
+
_watcher.close();
|
|
288513
|
+
} catch {
|
|
288514
|
+
}
|
|
288515
|
+
_watcher = null;
|
|
288516
|
+
}
|
|
288517
|
+
if (!_activeSessionId) {
|
|
288518
|
+
_lastTodos = [];
|
|
288519
|
+
applyHeightChange(0);
|
|
288520
|
+
return;
|
|
288521
|
+
}
|
|
288522
|
+
loadTodos();
|
|
288523
|
+
installWatcher();
|
|
288524
|
+
scheduleRedraw();
|
|
288525
|
+
}
|
|
288526
|
+
function onTuiTasksHeightChange(cb) {
|
|
288527
|
+
_onResizeChange = cb;
|
|
288528
|
+
}
|
|
288529
|
+
function setTuiTasksEnabled(enabled2) {
|
|
288530
|
+
_enabled = enabled2;
|
|
288531
|
+
scheduleRedraw();
|
|
288532
|
+
}
|
|
288533
|
+
function setTuiTasksScope(scope) {
|
|
288534
|
+
let changed = false;
|
|
288535
|
+
if (scope.overlayActive !== void 0 && scope.overlayActive !== _scopeOverlayActive) {
|
|
288536
|
+
_scopeOverlayActive = scope.overlayActive;
|
|
288537
|
+
changed = true;
|
|
288538
|
+
}
|
|
288539
|
+
if (scope.mainViewActive !== void 0 && scope.mainViewActive !== _scopeMainViewActive) {
|
|
288540
|
+
_scopeMainViewActive = scope.mainViewActive;
|
|
288541
|
+
changed = true;
|
|
288542
|
+
}
|
|
288543
|
+
if (scope.neovimActive !== void 0 && scope.neovimActive !== _scopeNeovimActive) {
|
|
288544
|
+
_scopeNeovimActive = scope.neovimActive;
|
|
288545
|
+
changed = true;
|
|
288546
|
+
}
|
|
288547
|
+
if (changed) {
|
|
288548
|
+
if (!panelEffectivelyVisible()) {
|
|
288549
|
+
applyHeightChange(0);
|
|
288550
|
+
} else {
|
|
288551
|
+
scheduleRedraw();
|
|
288552
|
+
}
|
|
288553
|
+
}
|
|
288554
|
+
}
|
|
288555
|
+
function getTuiTasksScope() {
|
|
288556
|
+
return {
|
|
288557
|
+
enabled: _enabled,
|
|
288558
|
+
overlayActive: _scopeOverlayActive,
|
|
288559
|
+
mainViewActive: _scopeMainViewActive,
|
|
288560
|
+
neovimActive: _scopeNeovimActive,
|
|
288561
|
+
visible: panelEffectivelyVisible()
|
|
288562
|
+
};
|
|
288563
|
+
}
|
|
288564
|
+
function refreshTuiTasks() {
|
|
288565
|
+
if (!_activeSessionId) return;
|
|
288566
|
+
loadTodos();
|
|
288567
|
+
scheduleRedraw();
|
|
288568
|
+
}
|
|
288569
|
+
function teardownTuiTasks() {
|
|
288570
|
+
if (_watcher) {
|
|
288571
|
+
try {
|
|
288572
|
+
_watcher.close();
|
|
288573
|
+
} catch {
|
|
288574
|
+
}
|
|
288575
|
+
_watcher = null;
|
|
288576
|
+
}
|
|
288577
|
+
_activeSessionId = null;
|
|
288578
|
+
_lastTodos = [];
|
|
288579
|
+
applyHeightChange(0);
|
|
288580
|
+
}
|
|
288581
|
+
function installWatcher() {
|
|
288582
|
+
if (!_activeSessionId) return;
|
|
288583
|
+
try {
|
|
288584
|
+
_watcher = fsWatch2(todoDir2(), { persistent: false }, (_evt, fname) => {
|
|
288585
|
+
if (!fname || !_activeSessionId) return;
|
|
288586
|
+
const expected = `${_activeSessionId.replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`;
|
|
288587
|
+
if (fname !== expected) return;
|
|
288588
|
+
loadTodos();
|
|
288589
|
+
scheduleRedraw();
|
|
288590
|
+
});
|
|
288591
|
+
} catch {
|
|
288592
|
+
}
|
|
288593
|
+
}
|
|
288594
|
+
function loadTodos() {
|
|
288595
|
+
if (!_activeSessionId) {
|
|
288596
|
+
_lastTodos = [];
|
|
288597
|
+
return;
|
|
288598
|
+
}
|
|
288599
|
+
try {
|
|
288600
|
+
const fp = todoPath2(_activeSessionId);
|
|
288601
|
+
if (!existsSync57(fp)) {
|
|
288602
|
+
_lastTodos = [];
|
|
288603
|
+
return;
|
|
288604
|
+
}
|
|
288605
|
+
const parsed = JSON.parse(readFileSync43(fp, "utf-8"));
|
|
288606
|
+
_lastTodos = Array.isArray(parsed) ? parsed : [];
|
|
288607
|
+
} catch {
|
|
288608
|
+
_lastTodos = [];
|
|
288609
|
+
}
|
|
288610
|
+
}
|
|
288611
|
+
function scheduleRedraw() {
|
|
288612
|
+
if (_redrawScheduled || !_enabled) return;
|
|
288613
|
+
_redrawScheduled = true;
|
|
288614
|
+
setImmediate(() => {
|
|
288615
|
+
_redrawScheduled = false;
|
|
288616
|
+
render();
|
|
288617
|
+
});
|
|
288618
|
+
}
|
|
288619
|
+
function computeTargetHeight() {
|
|
288620
|
+
if (!panelEffectivelyVisible()) return 0;
|
|
288621
|
+
if (!_lastTodos || _lastTodos.length === 0) return 0;
|
|
288622
|
+
const itemRows = Math.min(_lastTodos.length, MAX_VISIBLE_ROWS - 1);
|
|
288623
|
+
return 1 + itemRows;
|
|
288624
|
+
}
|
|
288625
|
+
function applyHeightChange(nextHeight) {
|
|
288626
|
+
const changed = setTasksHeight(nextHeight);
|
|
288627
|
+
if (changed) {
|
|
288628
|
+
notifyLayoutResize();
|
|
288629
|
+
}
|
|
288630
|
+
if (_onResizeChange) {
|
|
288631
|
+
try {
|
|
288632
|
+
_onResizeChange(nextHeight);
|
|
288633
|
+
} catch {
|
|
288634
|
+
}
|
|
288635
|
+
}
|
|
288636
|
+
}
|
|
288637
|
+
function statusToAnsi(status) {
|
|
288638
|
+
switch (status) {
|
|
288639
|
+
case "completed":
|
|
288640
|
+
return { mark: "◉", color: MUTED_GREEN, box: GREEN };
|
|
288641
|
+
case "in_progress":
|
|
288642
|
+
return { mark: "◐", color: GOLD, box: GOLD };
|
|
288643
|
+
case "blocked":
|
|
288644
|
+
return { mark: "◍", color: RED, box: RED };
|
|
288645
|
+
default:
|
|
288646
|
+
return { mark: "〇", color: GREY, box: GREY };
|
|
288647
|
+
}
|
|
288648
|
+
}
|
|
288649
|
+
function truncate2(s2, max) {
|
|
288650
|
+
if (s2.length <= max) return s2.padEnd(max, " ");
|
|
288651
|
+
return s2.slice(0, Math.max(0, max - 1)) + "…";
|
|
288652
|
+
}
|
|
288653
|
+
function render() {
|
|
288654
|
+
if (!_enabled) return;
|
|
288655
|
+
if (!panelEffectivelyVisible()) {
|
|
288656
|
+
applyHeightChange(0);
|
|
288657
|
+
return;
|
|
288658
|
+
}
|
|
288659
|
+
const target = computeTargetHeight();
|
|
288660
|
+
applyHeightChange(target);
|
|
288661
|
+
if (target === 0) return;
|
|
288662
|
+
const L = layout();
|
|
288663
|
+
const cols = Math.max(20, termCols());
|
|
288664
|
+
const completed = _lastTodos.filter((t2) => t2.status === "completed").length;
|
|
288665
|
+
const total = _lastTodos.length;
|
|
288666
|
+
const headerColor = completed === total ? GREEN : GOLD;
|
|
288667
|
+
const lines = [];
|
|
288668
|
+
const headerText = `tasks ${headerColor}${completed}/${total}${RESET}${DIM_LABEL} (todo_write)${RESET}`;
|
|
288669
|
+
lines.push(headerText);
|
|
288670
|
+
const visible = _lastTodos.slice(0, MAX_VISIBLE_ROWS - 1);
|
|
288671
|
+
for (const t2 of visible) {
|
|
288672
|
+
const { mark, color } = statusToAnsi(t2.status);
|
|
288673
|
+
const contentWidth = Math.max(4, cols - 8);
|
|
288674
|
+
const contentText = t2.content + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
|
|
288675
|
+
const truncated = truncate2(contentText, contentWidth);
|
|
288676
|
+
lines.push(`${color}${mark}${RESET} ${color}${truncated}${RESET}`);
|
|
288677
|
+
}
|
|
288678
|
+
if (_lastTodos.length > visible.length) {
|
|
288679
|
+
const more = _lastTodos.length - visible.length;
|
|
288680
|
+
lines[lines.length - 1] = `${DIM_LABEL}… +${more} more${RESET}`;
|
|
288681
|
+
}
|
|
288682
|
+
let out = HIDE + SAVE;
|
|
288683
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
288684
|
+
const row = L.tasksTop + i2;
|
|
288685
|
+
if (row > L.tasksBottom) break;
|
|
288686
|
+
out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET}`;
|
|
288687
|
+
}
|
|
288688
|
+
out += RESTORE + SHOW;
|
|
288689
|
+
try {
|
|
288690
|
+
process.stdout.write(out);
|
|
288691
|
+
} catch {
|
|
288692
|
+
}
|
|
288693
|
+
}
|
|
288694
|
+
var _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET, BG, DIM_LABEL, GOLD, GREEN, MUTED_GREEN, GREY, RED;
|
|
288695
|
+
var init_tui_tasks_renderer = __esm({
|
|
288696
|
+
"packages/cli/src/tui/tui-tasks-renderer.ts"() {
|
|
288697
|
+
"use strict";
|
|
288698
|
+
init_layout2();
|
|
288699
|
+
_activeSessionId = null;
|
|
288700
|
+
_watcher = null;
|
|
288701
|
+
_lastTodos = [];
|
|
288702
|
+
_enabled = true;
|
|
288703
|
+
_redrawScheduled = false;
|
|
288704
|
+
_onResizeChange = null;
|
|
288705
|
+
_scopeOverlayActive = false;
|
|
288706
|
+
_scopeMainViewActive = true;
|
|
288707
|
+
_scopeNeovimActive = false;
|
|
288708
|
+
MAX_VISIBLE_ROWS = 8;
|
|
288709
|
+
SAVE = "\x1B[s";
|
|
288710
|
+
RESTORE = "\x1B[u";
|
|
288711
|
+
HIDE = "\x1B[?25l";
|
|
288712
|
+
SHOW = "\x1B[?25h";
|
|
288713
|
+
CLEAR_LINE = "\x1B[2K";
|
|
288714
|
+
RESET = "\x1B[0m";
|
|
288715
|
+
BG = "\x1B[48;2;23;23;26m";
|
|
288716
|
+
DIM_LABEL = "\x1B[38;2;68;68;68m";
|
|
288717
|
+
GOLD = "\x1B[38;2;178;146;10m";
|
|
288718
|
+
GREEN = "\x1B[38;2;95;165;95m";
|
|
288719
|
+
MUTED_GREEN = "\x1B[38;2;74;122;74m";
|
|
288720
|
+
GREY = "\x1B[38;2;102;102;102m";
|
|
288721
|
+
RED = "\x1B[38;2;178;95;95m";
|
|
288469
288722
|
}
|
|
288470
288723
|
});
|
|
288471
288724
|
|
|
@@ -288479,7 +288732,7 @@ __export(status_bar_exports, {
|
|
|
288479
288732
|
setTerminalTitle: () => setTerminalTitle,
|
|
288480
288733
|
unlockFooterRedraws: () => unlockFooterRedraws
|
|
288481
288734
|
});
|
|
288482
|
-
import { readFileSync as
|
|
288735
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
288483
288736
|
function lockFooterRedraws() {
|
|
288484
288737
|
_globalFooterLock = true;
|
|
288485
288738
|
}
|
|
@@ -288499,7 +288752,7 @@ function setTerminalTitle(task, version4) {
|
|
|
288499
288752
|
const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
|
|
288500
288753
|
process.stdout.write(`\x1B]2;${title}\x07`);
|
|
288501
288754
|
}
|
|
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,
|
|
288755
|
+
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
288756
|
var init_status_bar = __esm({
|
|
288504
288757
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
288505
288758
|
"use strict";
|
|
@@ -288677,7 +288930,7 @@ var init_status_bar = __esm({
|
|
|
288677
288930
|
BOX_H = "─";
|
|
288678
288931
|
BOX_V = "│";
|
|
288679
288932
|
_globalFooterLock = false;
|
|
288680
|
-
|
|
288933
|
+
RESET2 = "\x1B[0m";
|
|
288681
288934
|
CURSOR_BLINK_BLOCK = "\x1B[1 q";
|
|
288682
288935
|
_isWindows = process.platform === "win32";
|
|
288683
288936
|
StatusBar = class _StatusBar {
|
|
@@ -289036,14 +289289,14 @@ var init_status_bar = __esm({
|
|
|
289036
289289
|
const hdrRow = layout().headerContent;
|
|
289037
289290
|
let buf = "\x1B7";
|
|
289038
289291
|
buf += `\x1B[${hdrRow};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
289039
|
-
buf += `${BOX_FG}│${
|
|
289292
|
+
buf += `${BOX_FG}│${RESET2}${PANEL_BG_SEQ}`;
|
|
289040
289293
|
buf += leftArrow;
|
|
289041
289294
|
buf += ` `;
|
|
289042
289295
|
buf += `\x1B[38;5;${TEXT_PRIMARY}m${PANEL_BG_SEQ}`;
|
|
289043
289296
|
buf += content;
|
|
289044
289297
|
buf += `\x1B[${hdrRow};${w - 1}H`;
|
|
289045
289298
|
buf += rightArrow;
|
|
289046
|
-
buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${
|
|
289299
|
+
buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${RESET2}`;
|
|
289047
289300
|
buf += "\x1B8";
|
|
289048
289301
|
this.termWrite(buf);
|
|
289049
289302
|
}
|
|
@@ -289433,7 +289686,7 @@ var init_status_bar = __esm({
|
|
|
289433
289686
|
if (nexusDir) {
|
|
289434
289687
|
try {
|
|
289435
289688
|
const metricsPath = nexusDir + "/remote-metrics.json";
|
|
289436
|
-
const raw =
|
|
289689
|
+
const raw = readFileSync44(metricsPath, "utf8");
|
|
289437
289690
|
const cached = JSON.parse(raw);
|
|
289438
289691
|
if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
|
|
289439
289692
|
const m2 = cached.data;
|
|
@@ -289968,6 +290221,8 @@ var init_status_bar = __esm({
|
|
|
289968
290221
|
this._activeViewId = id;
|
|
289969
290222
|
this._contentLines = view.contentLines;
|
|
289970
290223
|
this._contentScrollOffset = view.scrollOffset;
|
|
290224
|
+
Promise.resolve().then(() => (init_tui_tasks_renderer(), tui_tasks_renderer_exports)).then((m2) => m2.setTuiTasksScope({ mainViewActive: id === "main" })).catch(() => {
|
|
290225
|
+
});
|
|
289971
290226
|
this.repaintContent();
|
|
289972
290227
|
this.renderAgentTabs();
|
|
289973
290228
|
}
|
|
@@ -290116,11 +290371,11 @@ var init_status_bar = __esm({
|
|
|
290116
290371
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
290117
290372
|
const row = pos.inputStartRow + i2;
|
|
290118
290373
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
290119
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${
|
|
290374
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${RESET2}`;
|
|
290120
290375
|
}
|
|
290121
290376
|
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()}${
|
|
290377
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerP))}${BOX_BR}${RESET2}`;
|
|
290378
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}\x1B[?7h\x1B[${pos.scrollEnd};1H`;
|
|
290124
290379
|
this.termWrite(buf);
|
|
290125
290380
|
} else {
|
|
290126
290381
|
this.applyScrollRegion(true);
|
|
@@ -290262,7 +290517,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290262
290517
|
process.stdout.write = this._origWrite;
|
|
290263
290518
|
this._origWrite = null;
|
|
290264
290519
|
}
|
|
290265
|
-
process.stdout.write(
|
|
290520
|
+
process.stdout.write(RESET2);
|
|
290266
290521
|
this._brailleSpinner.setMetrics({ isStreaming: false });
|
|
290267
290522
|
this.renderFooterAndPositionInput();
|
|
290268
290523
|
this.scheduleMouseIdle();
|
|
@@ -290918,19 +291173,19 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290918
291173
|
const inputWrap = this.wrapInput(w);
|
|
290919
291174
|
let buf = "\x1B[?7l";
|
|
290920
291175
|
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}${
|
|
291176
|
+
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
291177
|
const spacerRow = pos.inputStartRow - 1;
|
|
290923
291178
|
if (spacerRow >= this.scrollRegionTop) {
|
|
290924
|
-
buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
291179
|
+
buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
|
|
290925
291180
|
}
|
|
290926
291181
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
290927
291182
|
const row = pos.inputStartRow + 1 + i2;
|
|
290928
291183
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
290929
291184
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
290930
291185
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
290931
|
-
buf += `${BOX_FG}${BOX_V}${
|
|
291186
|
+
buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
|
|
290932
291187
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
290933
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291188
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
290934
291189
|
}
|
|
290935
291190
|
const cursorTermRow = pos.inputStartRow + 1 + inputWrap.cursorRow;
|
|
290936
291191
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
@@ -290942,17 +291197,17 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290942
291197
|
const fg2 = isHighlighted ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
|
|
290943
291198
|
const slash = isHighlighted ? `\x1B[38;5;245m` : `\x1B[38;5;${TEXT_DIM}m`;
|
|
290944
291199
|
const marker = isHighlighted ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
|
|
290945
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${
|
|
291200
|
+
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}`;
|
|
290946
291201
|
buf += `${bg} ${marker}${slash}/${fg2}${cmd}`;
|
|
290947
291202
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
290948
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291203
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
290949
291204
|
}
|
|
290950
291205
|
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}${
|
|
291206
|
+
buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${RESET2}`;
|
|
290952
291207
|
} 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}${
|
|
291208
|
+
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
291209
|
}
|
|
290955
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
291210
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}`;
|
|
290956
291211
|
buf += "\x1B[?7h";
|
|
290957
291212
|
if (this.writeDepth === 0) {
|
|
290958
291213
|
buf += `\x1B[${cursorTermRow};${inputWrap.cursorCol}H${CURSOR_BLINK_BLOCK}\x1B[?25h`;
|
|
@@ -290985,7 +291240,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290985
291240
|
const pos = this.rowPositions(termRows());
|
|
290986
291241
|
let buf = "\x1B7\x1B[?7l";
|
|
290987
291242
|
if (pos.tabBarRow > 0) {
|
|
290988
|
-
buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
291243
|
+
buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
|
|
290989
291244
|
}
|
|
290990
291245
|
const boxInnerR = w - 2;
|
|
290991
291246
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
@@ -290995,14 +291250,14 @@ ${CONTENT_BG_SEQ}`);
|
|
|
290995
291250
|
const isHl = si === this._suggestIndex;
|
|
290996
291251
|
const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
|
|
290997
291252
|
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}${
|
|
291253
|
+
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}`;
|
|
291254
|
+
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
291000
291255
|
}
|
|
291001
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${
|
|
291256
|
+
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
291257
|
} 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}${
|
|
291258
|
+
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
291259
|
}
|
|
291005
|
-
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${
|
|
291260
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}\x1B[?7h\x1B8` + // DEC restore cursor
|
|
291006
291261
|
(this.writeDepth === 0 ? `${CURSOR_BLINK_BLOCK}\x1B[?25h` : "");
|
|
291007
291262
|
this.termWrite(buf);
|
|
291008
291263
|
if (pos.tabBarRow > 0) this.renderAgentTabs();
|
|
@@ -291036,16 +291291,16 @@ ${CONTENT_BG_SEQ}`);
|
|
|
291036
291291
|
}
|
|
291037
291292
|
buf += "\x1B[?7l";
|
|
291038
291293
|
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}${
|
|
291294
|
+
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
291295
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
291041
291296
|
const row = pos.inputStartRow + 1 + i2;
|
|
291042
291297
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
291043
291298
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
291044
|
-
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${
|
|
291299
|
+
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
291300
|
}
|
|
291046
291301
|
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()}${
|
|
291302
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerS))}${BOX_BR}${RESET2}`;
|
|
291303
|
+
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}`;
|
|
291049
291304
|
buf += "\x1B[?7h";
|
|
291050
291305
|
buf += "\x1B8";
|
|
291051
291306
|
if (heightDelta > 0) {
|
|
@@ -291062,9 +291317,9 @@ ${CONTENT_BG_SEQ}`);
|
|
|
291062
291317
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
291063
291318
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
291064
291319
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
|
|
291065
|
-
buf += `${BOX_FG}${BOX_V}${
|
|
291320
|
+
buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
|
|
291066
291321
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
291067
|
-
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${
|
|
291322
|
+
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
|
|
291068
291323
|
}
|
|
291069
291324
|
buf += "\x1B[?7h";
|
|
291070
291325
|
this.termWrite(buf);
|
|
@@ -291920,9 +292175,9 @@ __export(personaplex_exports, {
|
|
|
291920
292175
|
startPersonaPlexDaemon: () => startPersonaPlexDaemon,
|
|
291921
292176
|
stopPersonaPlex: () => stopPersonaPlex
|
|
291922
292177
|
});
|
|
291923
|
-
import { existsSync as
|
|
291924
|
-
import { join as
|
|
291925
|
-
import { homedir as
|
|
292178
|
+
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";
|
|
292179
|
+
import { join as join75, dirname as dirname21 } from "node:path";
|
|
292180
|
+
import { homedir as homedir25 } from "node:os";
|
|
291926
292181
|
import { execSync as execSync47, spawn as spawn21 } from "node:child_process";
|
|
291927
292182
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
291928
292183
|
function execAsync(cmd, opts = {}) {
|
|
@@ -291954,7 +292209,7 @@ function selectWeightTier(vramGB) {
|
|
|
291954
292209
|
}
|
|
291955
292210
|
function detectJetson() {
|
|
291956
292211
|
try {
|
|
291957
|
-
const model =
|
|
292212
|
+
const model = readFileSync45("/proc/device-tree/model", "utf8").replace(/\0/g, "").trim();
|
|
291958
292213
|
if (/jetson|orin|tegra/i.test(model)) {
|
|
291959
292214
|
const memInfo = execSync47("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
|
|
291960
292215
|
const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
|
|
@@ -292031,8 +292286,8 @@ function fileLink2(filePath, label) {
|
|
|
292031
292286
|
return `\x1B]8;;${url}\x1B\\${text}\x1B]8;;\x1B\\`;
|
|
292032
292287
|
}
|
|
292033
292288
|
function isPersonaPlexRunning() {
|
|
292034
|
-
if (!
|
|
292035
|
-
const pid = parseInt(
|
|
292289
|
+
if (!existsSync58(PID_FILE)) return false;
|
|
292290
|
+
const pid = parseInt(readFileSync45(PID_FILE, "utf8").trim(), 10);
|
|
292036
292291
|
if (isNaN(pid) || pid <= 0) return false;
|
|
292037
292292
|
try {
|
|
292038
292293
|
process.kill(pid, 0);
|
|
@@ -292043,18 +292298,18 @@ function isPersonaPlexRunning() {
|
|
|
292043
292298
|
}
|
|
292044
292299
|
function getPersonaPlexWSUrl() {
|
|
292045
292300
|
if (!isPersonaPlexRunning()) return null;
|
|
292046
|
-
if (!
|
|
292047
|
-
const port = parseInt(
|
|
292301
|
+
if (!existsSync58(PORT_FILE)) return null;
|
|
292302
|
+
const port = parseInt(readFileSync45(PORT_FILE, "utf8").trim(), 10);
|
|
292048
292303
|
return isNaN(port) ? null : `wss://127.0.0.1:${port}`;
|
|
292049
292304
|
}
|
|
292050
292305
|
function isPersonaPlexInstalled() {
|
|
292051
|
-
return
|
|
292306
|
+
return existsSync58(join75(PERSONAPLEX_DIR, "model_ready"));
|
|
292052
292307
|
}
|
|
292053
292308
|
function getWeightTier() {
|
|
292054
292309
|
const detected = detectPersonaPlexCapability();
|
|
292055
|
-
const tierFile =
|
|
292056
|
-
if (
|
|
292057
|
-
const saved =
|
|
292310
|
+
const tierFile = join75(PERSONAPLEX_DIR, "weight_tier");
|
|
292311
|
+
if (existsSync58(tierFile)) {
|
|
292312
|
+
const saved = readFileSync45(tierFile, "utf8").trim();
|
|
292058
292313
|
if (saved in WEIGHT_REPOS) {
|
|
292059
292314
|
const vram = detected.vramGB;
|
|
292060
292315
|
if (saved === "nf4-distilled" && vram < 24) {
|
|
@@ -292080,8 +292335,8 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292080
292335
|
}
|
|
292081
292336
|
const isAarch64 = arch2 === "aarch64" || arch2 === "arm64";
|
|
292082
292337
|
if (isAarch64) log22(`Detected ARM64 platform (${arch2}) — Jetson/ARM install path`);
|
|
292083
|
-
const venvDir =
|
|
292084
|
-
if (!
|
|
292338
|
+
const venvDir = join75(PERSONAPLEX_DIR, "venv");
|
|
292339
|
+
if (!existsSync58(venvDir)) {
|
|
292085
292340
|
log22("Creating Python virtual environment...");
|
|
292086
292341
|
try {
|
|
292087
292342
|
const ssp = isAarch64 ? " --system-site-packages" : "";
|
|
@@ -292091,8 +292346,8 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292091
292346
|
return false;
|
|
292092
292347
|
}
|
|
292093
292348
|
}
|
|
292094
|
-
const pip = process.platform === "win32" ?
|
|
292095
|
-
const python = process.platform === "win32" ?
|
|
292349
|
+
const pip = process.platform === "win32" ? join75(venvDir, "Scripts", "pip.exe") : join75(venvDir, "bin", "pip");
|
|
292350
|
+
const python = process.platform === "win32" ? join75(venvDir, "Scripts", "python.exe") : join75(venvDir, "bin", "python3");
|
|
292096
292351
|
log22("Checking system dependencies (libopus)...");
|
|
292097
292352
|
try {
|
|
292098
292353
|
if (process.platform === "linux") {
|
|
@@ -292122,9 +292377,9 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292122
292377
|
}
|
|
292123
292378
|
}
|
|
292124
292379
|
log22("Installing PersonaPlex (moshi package)...");
|
|
292125
|
-
const repoDir =
|
|
292380
|
+
const repoDir = join75(PERSONAPLEX_DIR, "personaplex-repo");
|
|
292126
292381
|
try {
|
|
292127
|
-
if (!
|
|
292382
|
+
if (!existsSync58(repoDir)) {
|
|
292128
292383
|
await execAsync(
|
|
292129
292384
|
`git clone https://github.com/NVIDIA/personaplex.git "${repoDir}"`,
|
|
292130
292385
|
{ timeout: 12e4 }
|
|
@@ -292148,7 +292403,7 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292148
292403
|
if (isAarch64) {
|
|
292149
292404
|
log22("ARM64: Installing moshi (--no-deps to preserve JetPack torch)...");
|
|
292150
292405
|
await execAsync(
|
|
292151
|
-
`"${pip}" install --quiet --no-deps "${
|
|
292406
|
+
`"${pip}" install --quiet --no-deps "${join75(repoDir, "moshi")}/."`,
|
|
292152
292407
|
{ timeout: 3e5 }
|
|
292153
292408
|
);
|
|
292154
292409
|
log22("ARM64: Installing remaining moshi dependencies...");
|
|
@@ -292158,7 +292413,7 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292158
292413
|
);
|
|
292159
292414
|
} else {
|
|
292160
292415
|
await execAsync(
|
|
292161
|
-
`"${pip}" install --quiet "${
|
|
292416
|
+
`"${pip}" install --quiet "${join75(repoDir, "moshi")}/."`,
|
|
292162
292417
|
{ timeout: 6e5 }
|
|
292163
292418
|
// 10 min — torch download is ~2.5GB
|
|
292164
292419
|
);
|
|
@@ -292176,16 +292431,16 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292176
292431
|
}
|
|
292177
292432
|
return false;
|
|
292178
292433
|
}
|
|
292179
|
-
const serverPy =
|
|
292434
|
+
const serverPy = join75(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
|
|
292180
292435
|
try {
|
|
292181
292436
|
const sitePackages = execSync47(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
|
|
292182
292437
|
encoding: "utf8",
|
|
292183
292438
|
timeout: 5e3,
|
|
292184
292439
|
stdio: "pipe"
|
|
292185
292440
|
}).trim();
|
|
292186
|
-
const serverFile =
|
|
292187
|
-
if (
|
|
292188
|
-
let src2 =
|
|
292441
|
+
const serverFile = join75(sitePackages, "server.py");
|
|
292442
|
+
if (existsSync58(serverFile)) {
|
|
292443
|
+
let src2 = readFileSync45(serverFile, "utf8");
|
|
292189
292444
|
if (src2.includes('int(request["seed"])')) {
|
|
292190
292445
|
src2 = src2.replace('int(request["seed"])', 'int(request.query["seed"])');
|
|
292191
292446
|
writeFileSync29(serverFile, src2);
|
|
@@ -292200,9 +292455,9 @@ async function installPersonaPlex(onInfo, weightTier) {
|
|
|
292200
292455
|
timeout: 5e3,
|
|
292201
292456
|
stdio: "pipe"
|
|
292202
292457
|
}).trim();
|
|
292203
|
-
const loadersFile =
|
|
292204
|
-
if (
|
|
292205
|
-
let src2 =
|
|
292458
|
+
const loadersFile = join75(sitePackages, "models", "loaders.py");
|
|
292459
|
+
if (existsSync58(loadersFile)) {
|
|
292460
|
+
let src2 = readFileSync45(loadersFile, "utf8");
|
|
292206
292461
|
if (!src2.includes("_dequantize_2bit_state_dict")) {
|
|
292207
292462
|
const dequantPatch = `
|
|
292208
292463
|
import math
|
|
@@ -292304,30 +292559,30 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292304
292559
|
timeout: 5e3,
|
|
292305
292560
|
stdio: "pipe"
|
|
292306
292561
|
}).trim();
|
|
292307
|
-
const hybridDest =
|
|
292308
|
-
const serverDest =
|
|
292309
|
-
if (!
|
|
292562
|
+
const hybridDest = join75(sitePackages2, "hybrid_agent.py");
|
|
292563
|
+
const serverDest = join75(sitePackages2, "server.py");
|
|
292564
|
+
if (!existsSync58(hybridDest) || !readFileSync45(hybridDest, "utf8").includes("OA_API_BASE")) {
|
|
292310
292565
|
log22("Deploying hybrid_agent.py (OA API integration)...");
|
|
292311
292566
|
try {
|
|
292312
292567
|
await execAsync(
|
|
292313
292568
|
`curl -sL "https://raw.githubusercontent.com/robit-man/personaplex/main/personaplex-setup/moshi/moshi/hybrid_agent.py" -o "${hybridDest}"`,
|
|
292314
292569
|
{ timeout: 3e4 }
|
|
292315
292570
|
);
|
|
292316
|
-
if (
|
|
292571
|
+
if (existsSync58(hybridDest) && readFileSync45(hybridDest, "utf8").includes("OA_API_BASE")) {
|
|
292317
292572
|
log22("hybrid_agent.py deployed (OA API + Ollama fallback).");
|
|
292318
292573
|
}
|
|
292319
292574
|
} catch {
|
|
292320
292575
|
log22("hybrid_agent.py download failed — hybrid mode will be disabled.");
|
|
292321
292576
|
}
|
|
292322
292577
|
}
|
|
292323
|
-
if (!
|
|
292578
|
+
if (!readFileSync45(serverDest, "utf8").includes("hybrid_agent")) {
|
|
292324
292579
|
log22("Deploying patched server.py (hybrid mode + API endpoints)...");
|
|
292325
292580
|
try {
|
|
292326
292581
|
await execAsync(
|
|
292327
292582
|
`curl -sL "https://raw.githubusercontent.com/robit-man/personaplex/main/personaplex-setup/moshi/moshi/server.py" -o "${serverDest}"`,
|
|
292328
292583
|
{ timeout: 3e4 }
|
|
292329
292584
|
);
|
|
292330
|
-
if (
|
|
292585
|
+
if (readFileSync45(serverDest, "utf8").includes("hybrid_agent")) {
|
|
292331
292586
|
log22("server.py patched with hybrid intercept + REST APIs.");
|
|
292332
292587
|
}
|
|
292333
292588
|
} catch {
|
|
@@ -292390,7 +292645,7 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292390
292645
|
await execAsync(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('${nf4.repo}', '${nf4.file}', token=False)"`, {
|
|
292391
292646
|
timeout: 6e5
|
|
292392
292647
|
});
|
|
292393
|
-
writeFileSync29(
|
|
292648
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "weight_tier"), "nf4");
|
|
292394
292649
|
log22(`Downloaded INT4 weights instead (${nf4.sizeGB}GB, public).`);
|
|
292395
292650
|
} catch {
|
|
292396
292651
|
log22("Weight download failed.");
|
|
@@ -292402,8 +292657,8 @@ $2if filename.endswith(".safetensors"):`
|
|
|
292402
292657
|
log22("Weights will download on first server launch.");
|
|
292403
292658
|
}
|
|
292404
292659
|
}
|
|
292405
|
-
writeFileSync29(
|
|
292406
|
-
writeFileSync29(
|
|
292660
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "weight_tier"), tier);
|
|
292661
|
+
writeFileSync29(join75(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
|
|
292407
292662
|
log22(`PersonaPlex installed (${tier} tier). Use /call to start voice session.`);
|
|
292408
292663
|
return true;
|
|
292409
292664
|
}
|
|
@@ -292423,14 +292678,14 @@ async function startPersonaPlexDaemon(onInfo) {
|
|
|
292423
292678
|
return null;
|
|
292424
292679
|
}
|
|
292425
292680
|
mkdirSync32(PERSONAPLEX_DIR, { recursive: true });
|
|
292426
|
-
const venvPython2 = process.platform === "win32" ?
|
|
292427
|
-
const sslDir =
|
|
292681
|
+
const venvPython2 = process.platform === "win32" ? join75(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join75(PERSONAPLEX_DIR, "venv", "bin", "python3");
|
|
292682
|
+
const sslDir = join75(PERSONAPLEX_DIR, "ssl");
|
|
292428
292683
|
mkdirSync32(sslDir, { recursive: true });
|
|
292429
292684
|
const tier = getWeightTier();
|
|
292430
292685
|
const repoInfo = WEIGHT_REPOS[tier];
|
|
292431
292686
|
const extraArgs = [];
|
|
292432
292687
|
if (tier !== "original") {
|
|
292433
|
-
const cachedBf16 =
|
|
292688
|
+
const cachedBf16 = join75(PERSONAPLEX_DIR, "model-bf16-cache.safetensors");
|
|
292434
292689
|
if (tier === "nf4-distilled") {
|
|
292435
292690
|
log22(`Weight tier: ${tier} — distilled NF4 (90% token match, ${repoInfo.sizeGB}GB)...`);
|
|
292436
292691
|
try {
|
|
@@ -292438,8 +292693,8 @@ async function startPersonaPlexDaemon(onInfo) {
|
|
|
292438
292693
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`,
|
|
292439
292694
|
{ encoding: "utf8", timeout: 6e4, stdio: "pipe" }
|
|
292440
292695
|
).trim();
|
|
292441
|
-
if (
|
|
292442
|
-
if (!
|
|
292696
|
+
if (existsSync58(weightPath)) {
|
|
292697
|
+
if (!existsSync58(cachedBf16)) {
|
|
292443
292698
|
log22("Converting .pt checkpoint to safetensors (one-time)...");
|
|
292444
292699
|
execSync47(
|
|
292445
292700
|
`"${venvPython2}" -c "
|
|
@@ -292452,7 +292707,7 @@ print('Converted')
|
|
|
292452
292707
|
{ timeout: 18e4, stdio: "pipe" }
|
|
292453
292708
|
);
|
|
292454
292709
|
}
|
|
292455
|
-
if (
|
|
292710
|
+
if (existsSync58(cachedBf16)) {
|
|
292456
292711
|
extraArgs.push("--moshi-weight", cachedBf16);
|
|
292457
292712
|
log22(`Using distilled weights: ${(statSync17(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
|
|
292458
292713
|
} else {
|
|
@@ -292464,12 +292719,12 @@ print('Converted')
|
|
|
292464
292719
|
}
|
|
292465
292720
|
} else {
|
|
292466
292721
|
log22(`Weight tier: ${tier} (${repoInfo.sizeGB}GB) — dequantizing to bf16 cache...`);
|
|
292467
|
-
const dequantScript =
|
|
292468
|
-
if (!
|
|
292722
|
+
const dequantScript = join75(PERSONAPLEX_DIR, "dequant-loader.py");
|
|
292723
|
+
if (!existsSync58(dequantScript)) {
|
|
292469
292724
|
const shipped = getShippedVoicesDir();
|
|
292470
292725
|
if (shipped) {
|
|
292471
|
-
const src2 =
|
|
292472
|
-
if (
|
|
292726
|
+
const src2 = join75(shipped, "dequant-loader.py");
|
|
292727
|
+
if (existsSync58(src2)) copyFileSync2(src2, dequantScript);
|
|
292473
292728
|
}
|
|
292474
292729
|
}
|
|
292475
292730
|
try {
|
|
@@ -292477,13 +292732,13 @@ print('Converted')
|
|
|
292477
292732
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`,
|
|
292478
292733
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292479
292734
|
).trim();
|
|
292480
|
-
if (
|
|
292735
|
+
if (existsSync58(dequantScript) && existsSync58(weightPath)) {
|
|
292481
292736
|
try {
|
|
292482
292737
|
execSync47(
|
|
292483
292738
|
`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`,
|
|
292484
292739
|
{ timeout: 3e5, stdio: "pipe" }
|
|
292485
292740
|
);
|
|
292486
|
-
if (
|
|
292741
|
+
if (existsSync58(cachedBf16)) {
|
|
292487
292742
|
extraArgs.push("--moshi-weight", cachedBf16);
|
|
292488
292743
|
log22(`Using dequantized cache: ${(statSync17(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
|
|
292489
292744
|
}
|
|
@@ -292496,7 +292751,7 @@ print('Converted')
|
|
|
292496
292751
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`,
|
|
292497
292752
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292498
292753
|
).trim();
|
|
292499
|
-
if (
|
|
292754
|
+
if (existsSync58(mimiPath)) extraArgs.push("--mimi-weight", mimiPath);
|
|
292500
292755
|
} catch {
|
|
292501
292756
|
}
|
|
292502
292757
|
try {
|
|
@@ -292504,7 +292759,7 @@ print('Converted')
|
|
|
292504
292759
|
`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`,
|
|
292505
292760
|
{ encoding: "utf8", timeout: 3e4, stdio: "pipe" }
|
|
292506
292761
|
).trim();
|
|
292507
|
-
if (
|
|
292762
|
+
if (existsSync58(tokPath)) extraArgs.push("--tokenizer", tokPath);
|
|
292508
292763
|
} catch {
|
|
292509
292764
|
}
|
|
292510
292765
|
} catch {
|
|
@@ -292517,7 +292772,7 @@ print('Converted')
|
|
|
292517
292772
|
let ollamaModel = process.env["HYBRID_LLM_MODEL"] || "";
|
|
292518
292773
|
if (!ollamaModel) {
|
|
292519
292774
|
try {
|
|
292520
|
-
const oaConfig = JSON.parse(
|
|
292775
|
+
const oaConfig = JSON.parse(readFileSync45(join75(homedir25(), ".open-agents", "config.json"), "utf8"));
|
|
292521
292776
|
if (oaConfig.model) ollamaModel = oaConfig.model;
|
|
292522
292777
|
} catch {
|
|
292523
292778
|
}
|
|
@@ -292616,8 +292871,8 @@ print('Converted')
|
|
|
292616
292871
|
return null;
|
|
292617
292872
|
}
|
|
292618
292873
|
function stopPersonaPlex() {
|
|
292619
|
-
if (!
|
|
292620
|
-
const pid = parseInt(
|
|
292874
|
+
if (!existsSync58(PID_FILE)) return;
|
|
292875
|
+
const pid = parseInt(readFileSync45(PID_FILE, "utf8").trim(), 10);
|
|
292621
292876
|
if (isNaN(pid) || pid <= 0) return;
|
|
292622
292877
|
try {
|
|
292623
292878
|
if (process.platform === "win32") {
|
|
@@ -292653,12 +292908,12 @@ function listPersonaPlexVoices() {
|
|
|
292653
292908
|
for (const name10 of builtins) {
|
|
292654
292909
|
voices.push({ name: name10, type: "builtin", path: `${name10}.pt` });
|
|
292655
292910
|
}
|
|
292656
|
-
if (
|
|
292911
|
+
if (existsSync58(CUSTOM_VOICES_DIR)) {
|
|
292657
292912
|
try {
|
|
292658
292913
|
for (const f2 of readdirSync15(CUSTOM_VOICES_DIR)) {
|
|
292659
292914
|
if (f2.endsWith(".pt")) {
|
|
292660
292915
|
const name10 = f2.replace(/\.pt$/, "");
|
|
292661
|
-
voices.push({ name: name10, type: "custom", path:
|
|
292916
|
+
voices.push({ name: name10, type: "custom", path: join75(CUSTOM_VOICES_DIR, f2) });
|
|
292662
292917
|
}
|
|
292663
292918
|
}
|
|
292664
292919
|
} catch {
|
|
@@ -292673,19 +292928,19 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292673
292928
|
log22("PersonaPlex not installed. Run /voice personaplex first.");
|
|
292674
292929
|
return null;
|
|
292675
292930
|
}
|
|
292676
|
-
if (!
|
|
292931
|
+
if (!existsSync58(inputWav)) {
|
|
292677
292932
|
log22(`Input WAV not found: ${inputWav}`);
|
|
292678
292933
|
return null;
|
|
292679
292934
|
}
|
|
292680
292935
|
mkdirSync32(CUSTOM_VOICES_DIR, { recursive: true });
|
|
292681
|
-
const outputPt =
|
|
292682
|
-
if (
|
|
292936
|
+
const outputPt = join75(CUSTOM_VOICES_DIR, `${voiceName}.pt`);
|
|
292937
|
+
if (existsSync58(outputPt)) {
|
|
292683
292938
|
log22(`Voice "${voiceName}" already exists. Delete ${outputPt} to re-clone.`);
|
|
292684
292939
|
return outputPt;
|
|
292685
292940
|
}
|
|
292686
|
-
const venvPython2 = process.platform === "win32" ?
|
|
292687
|
-
const cloneScript =
|
|
292688
|
-
if (!
|
|
292941
|
+
const venvPython2 = process.platform === "win32" ? join75(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join75(PERSONAPLEX_DIR, "venv", "bin", "python3");
|
|
292942
|
+
const cloneScript = join75(PERSONAPLEX_DIR, "clone-voice.py");
|
|
292943
|
+
if (!existsSync58(cloneScript)) {
|
|
292689
292944
|
log22("clone-voice.py not found. Reinstall PersonaPlex.");
|
|
292690
292945
|
return null;
|
|
292691
292946
|
}
|
|
@@ -292717,7 +292972,7 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292717
292972
|
output += d2.toString();
|
|
292718
292973
|
});
|
|
292719
292974
|
child.on("close", (code8) => {
|
|
292720
|
-
if (code8 === 0 &&
|
|
292975
|
+
if (code8 === 0 && existsSync58(outputPt)) {
|
|
292721
292976
|
log22(`Voice "${voiceName}" cloned successfully.`);
|
|
292722
292977
|
resolve39(outputPt);
|
|
292723
292978
|
} else {
|
|
@@ -292729,19 +292984,19 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
|
|
|
292729
292984
|
}
|
|
292730
292985
|
function getShippedVoicesDir() {
|
|
292731
292986
|
const candidates = [
|
|
292732
|
-
|
|
292987
|
+
join75(PERSONAPLEX_DIR, "shipped_voices"),
|
|
292733
292988
|
// cached copy
|
|
292734
|
-
|
|
292989
|
+
join75(process.cwd(), "voices", "personaplex")
|
|
292735
292990
|
// repo root
|
|
292736
292991
|
];
|
|
292737
292992
|
try {
|
|
292738
292993
|
const modDir = dirname21(fileURLToPath12(import.meta.url));
|
|
292739
|
-
candidates.push(
|
|
292740
|
-
candidates.push(
|
|
292994
|
+
candidates.push(join75(modDir, "..", "..", "..", "voices", "personaplex"));
|
|
292995
|
+
candidates.push(join75(modDir, "..", "..", "..", "..", "voices", "personaplex"));
|
|
292741
292996
|
} catch {
|
|
292742
292997
|
}
|
|
292743
292998
|
for (const dir of candidates) {
|
|
292744
|
-
if (
|
|
292999
|
+
if (existsSync58(dir)) {
|
|
292745
293000
|
try {
|
|
292746
293001
|
const files = readdirSync15(dir);
|
|
292747
293002
|
if (files.some((f2) => f2.endsWith(".pt"))) return dir;
|
|
@@ -292762,14 +293017,14 @@ function provisionShippedVoices(onInfo) {
|
|
|
292762
293017
|
try {
|
|
292763
293018
|
for (const f2 of readdirSync15(shippedDir)) {
|
|
292764
293019
|
if (!f2.endsWith(".pt")) continue;
|
|
292765
|
-
const customDst =
|
|
292766
|
-
if (!
|
|
292767
|
-
copyFileSync2(
|
|
293020
|
+
const customDst = join75(CUSTOM_VOICES_DIR, f2);
|
|
293021
|
+
if (!existsSync58(customDst)) {
|
|
293022
|
+
copyFileSync2(join75(shippedDir, f2), customDst);
|
|
292768
293023
|
}
|
|
292769
293024
|
if (hfVoicesDir) {
|
|
292770
|
-
const hfDst =
|
|
292771
|
-
if (!
|
|
292772
|
-
copyFileSync2(
|
|
293025
|
+
const hfDst = join75(hfVoicesDir, f2);
|
|
293026
|
+
if (!existsSync58(hfDst)) {
|
|
293027
|
+
copyFileSync2(join75(shippedDir, f2), hfDst);
|
|
292773
293028
|
log22(`Deployed voice: ${f2.replace(".pt", "")}`);
|
|
292774
293029
|
deployed++;
|
|
292775
293030
|
}
|
|
@@ -292777,9 +293032,9 @@ function provisionShippedVoices(onInfo) {
|
|
|
292777
293032
|
}
|
|
292778
293033
|
} catch {
|
|
292779
293034
|
}
|
|
292780
|
-
const shippedScript =
|
|
292781
|
-
const targetScript =
|
|
292782
|
-
if (
|
|
293035
|
+
const shippedScript = join75(shippedDir, "clone-voice.py");
|
|
293036
|
+
const targetScript = join75(PERSONAPLEX_DIR, "clone-voice.py");
|
|
293037
|
+
if (existsSync58(shippedScript) && !existsSync58(targetScript)) {
|
|
292783
293038
|
try {
|
|
292784
293039
|
copyFileSync2(shippedScript, targetScript);
|
|
292785
293040
|
} catch {
|
|
@@ -292788,14 +293043,14 @@ function provisionShippedVoices(onInfo) {
|
|
|
292788
293043
|
return deployed;
|
|
292789
293044
|
}
|
|
292790
293045
|
function getHFVoicesDir() {
|
|
292791
|
-
const hfBase =
|
|
292792
|
-
if (!
|
|
293046
|
+
const hfBase = join75(homedir25(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
|
|
293047
|
+
if (!existsSync58(hfBase)) return null;
|
|
292793
293048
|
try {
|
|
292794
|
-
const snapshots =
|
|
292795
|
-
if (!
|
|
293049
|
+
const snapshots = join75(hfBase, "snapshots");
|
|
293050
|
+
if (!existsSync58(snapshots)) return null;
|
|
292796
293051
|
for (const snap of readdirSync15(snapshots)) {
|
|
292797
|
-
const voicesDir =
|
|
292798
|
-
if (
|
|
293052
|
+
const voicesDir = join75(snapshots, snap, "voices");
|
|
293053
|
+
if (existsSync58(voicesDir)) return voicesDir;
|
|
292799
293054
|
}
|
|
292800
293055
|
} catch {
|
|
292801
293056
|
}
|
|
@@ -292804,19 +293059,19 @@ function getHFVoicesDir() {
|
|
|
292804
293059
|
function patchFrontendVoiceList(onInfo) {
|
|
292805
293060
|
const log22 = onInfo ?? (() => {
|
|
292806
293061
|
});
|
|
292807
|
-
const hfBase =
|
|
292808
|
-
if (!
|
|
293062
|
+
const hfBase = join75(homedir25(), ".cache", "huggingface", "hub", "models--nvidia--personaplex-7b-v1");
|
|
293063
|
+
if (!existsSync58(hfBase)) return;
|
|
292809
293064
|
try {
|
|
292810
|
-
const snapshots =
|
|
293065
|
+
const snapshots = join75(hfBase, "snapshots");
|
|
292811
293066
|
for (const snap of readdirSync15(snapshots)) {
|
|
292812
|
-
const distDir =
|
|
292813
|
-
if (!
|
|
293067
|
+
const distDir = join75(snapshots, snap, "dist", "assets");
|
|
293068
|
+
if (!existsSync58(distDir)) continue;
|
|
292814
293069
|
for (const f2 of readdirSync15(distDir)) {
|
|
292815
293070
|
if (!f2.startsWith("index-") || !f2.endsWith(".js")) continue;
|
|
292816
|
-
const jsPath =
|
|
292817
|
-
let js =
|
|
293071
|
+
const jsPath = join75(distDir, f2);
|
|
293072
|
+
let js = readFileSync45(jsPath, "utf8");
|
|
292818
293073
|
const customVoices = [];
|
|
292819
|
-
if (
|
|
293074
|
+
if (existsSync58(CUSTOM_VOICES_DIR)) {
|
|
292820
293075
|
for (const vf of readdirSync15(CUSTOM_VOICES_DIR)) {
|
|
292821
293076
|
if (vf.endsWith(".pt")) {
|
|
292822
293077
|
const name10 = vf.replace(".pt", "");
|
|
@@ -292882,11 +293137,11 @@ var init_personaplex = __esm({
|
|
|
292882
293137
|
nf4: { repo: "cudabenchmarktest/personaplex-7b-nf4", file: "model-nf4.safetensors", sizeGB: 4.1, needsToken: false },
|
|
292883
293138
|
"nf4-distilled": { repo: "cudabenchmarktest/personaplex-7b-nf4-distilled", file: "student_best.pt", sizeGB: 16.7, needsToken: false }
|
|
292884
293139
|
};
|
|
292885
|
-
PERSONAPLEX_DIR =
|
|
292886
|
-
PID_FILE =
|
|
292887
|
-
PORT_FILE =
|
|
292888
|
-
LOG_FILE =
|
|
292889
|
-
CUSTOM_VOICES_DIR =
|
|
293140
|
+
PERSONAPLEX_DIR = join75(homedir25(), ".open-agents", "voice", "personaplex");
|
|
293141
|
+
PID_FILE = join75(PERSONAPLEX_DIR, "daemon.pid");
|
|
293142
|
+
PORT_FILE = join75(PERSONAPLEX_DIR, "daemon.port");
|
|
293143
|
+
LOG_FILE = join75(PERSONAPLEX_DIR, "daemon.log");
|
|
293144
|
+
CUSTOM_VOICES_DIR = join75(PERSONAPLEX_DIR, "custom_voices");
|
|
292890
293145
|
}
|
|
292891
293146
|
});
|
|
292892
293147
|
|
|
@@ -292927,9 +293182,9 @@ __export(setup_exports, {
|
|
|
292927
293182
|
import * as readline from "node:readline";
|
|
292928
293183
|
import { execSync as execSync48, spawn as spawn22, exec as exec4 } from "node:child_process";
|
|
292929
293184
|
import { promisify as promisify7 } from "node:util";
|
|
292930
|
-
import { existsSync as
|
|
292931
|
-
import { join as
|
|
292932
|
-
import { homedir as
|
|
293185
|
+
import { existsSync as existsSync59, writeFileSync as writeFileSync30, readFileSync as readFileSync46, appendFileSync as appendFileSync2, mkdirSync as mkdirSync33 } from "node:fs";
|
|
293186
|
+
import { join as join76 } from "node:path";
|
|
293187
|
+
import { homedir as homedir26, platform as platform3 } from "node:os";
|
|
292933
293188
|
async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
|
|
292934
293189
|
if (_toolSupportCache.has(modelName)) return _toolSupportCache.get(modelName);
|
|
292935
293190
|
try {
|
|
@@ -293321,7 +293576,7 @@ async function installOllamaMac(_rl) {
|
|
|
293321
293576
|
);
|
|
293322
293577
|
if (!hasCmd("brew")) {
|
|
293323
293578
|
try {
|
|
293324
|
-
const brewPrefix =
|
|
293579
|
+
const brewPrefix = existsSync59("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
293325
293580
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
293326
293581
|
} catch {
|
|
293327
293582
|
}
|
|
@@ -294106,9 +294361,9 @@ async function doSetup(config, rl) {
|
|
|
294106
294361
|
`PARAMETER num_predict ${numPredict}`,
|
|
294107
294362
|
`PARAMETER stop "<|endoftext|>"`
|
|
294108
294363
|
].join("\n");
|
|
294109
|
-
const modelDir2 =
|
|
294364
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294110
294365
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294111
|
-
const modelfilePath =
|
|
294366
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294112
294367
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294113
294368
|
process.stdout.write(` ${c3.dim("Creating model...")} `);
|
|
294114
294369
|
execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
@@ -294154,7 +294409,7 @@ async function isModelAvailable(config) {
|
|
|
294154
294409
|
}
|
|
294155
294410
|
function isFirstRun() {
|
|
294156
294411
|
try {
|
|
294157
|
-
return !
|
|
294412
|
+
return !existsSync59(join76(homedir26(), ".open-agents", "config.json"));
|
|
294158
294413
|
} catch {
|
|
294159
294414
|
return true;
|
|
294160
294415
|
}
|
|
@@ -294202,7 +294457,7 @@ function detectPkgManager() {
|
|
|
294202
294457
|
return null;
|
|
294203
294458
|
}
|
|
294204
294459
|
function getVenvDir() {
|
|
294205
|
-
return
|
|
294460
|
+
return join76(homedir26(), ".open-agents", "venv");
|
|
294206
294461
|
}
|
|
294207
294462
|
function hasVenvModule() {
|
|
294208
294463
|
try {
|
|
@@ -294215,10 +294470,10 @@ function hasVenvModule() {
|
|
|
294215
294470
|
function ensureVenv(log22) {
|
|
294216
294471
|
const venvDir = getVenvDir();
|
|
294217
294472
|
const isWin2 = process.platform === "win32";
|
|
294218
|
-
const pipPath = isWin2 ?
|
|
294219
|
-
const venvPyPath = isWin2 ?
|
|
294473
|
+
const pipPath = isWin2 ? join76(venvDir, "Scripts", "pip.exe") : join76(venvDir, "bin", "pip");
|
|
294474
|
+
const venvPyPath = isWin2 ? join76(venvDir, "Scripts", "python.exe") : join76(venvDir, "bin", "python3");
|
|
294220
294475
|
const pythonCmd = isWin2 ? "python" : "python3";
|
|
294221
|
-
if (
|
|
294476
|
+
if (existsSync59(pipPath)) {
|
|
294222
294477
|
try {
|
|
294223
294478
|
execSync48(`"${venvPyPath}" -m pip --version`, { stdio: "pipe", timeout: 1e4 });
|
|
294224
294479
|
return venvDir;
|
|
@@ -294249,7 +294504,7 @@ function ensureVenv(log22) {
|
|
|
294249
294504
|
return null;
|
|
294250
294505
|
}
|
|
294251
294506
|
try {
|
|
294252
|
-
mkdirSync33(
|
|
294507
|
+
mkdirSync33(join76(homedir26(), ".open-agents"), { recursive: true });
|
|
294253
294508
|
const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
|
|
294254
294509
|
execSync48(`${pyCmd} -m venv --clear "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
294255
294510
|
try {
|
|
@@ -294358,12 +294613,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294358
294613
|
];
|
|
294359
294614
|
{
|
|
294360
294615
|
const pm2 = detectPkgManager();
|
|
294361
|
-
const _visionMarkerDir =
|
|
294362
|
-
const _visionMarkerFile =
|
|
294616
|
+
const _visionMarkerDir = join76(homedir26(), ".open-agents");
|
|
294617
|
+
const _visionMarkerFile = join76(_visionMarkerDir, "vision-deps-installed.json");
|
|
294363
294618
|
let _visionPreviouslyInstalled = /* @__PURE__ */ new Set();
|
|
294364
294619
|
try {
|
|
294365
|
-
if (
|
|
294366
|
-
const _vm = JSON.parse(
|
|
294620
|
+
if (existsSync59(_visionMarkerFile)) {
|
|
294621
|
+
const _vm = JSON.parse(readFileSync46(_visionMarkerFile, "utf8"));
|
|
294367
294622
|
_visionPreviouslyInstalled = new Set(_vm.installed || []);
|
|
294368
294623
|
}
|
|
294369
294624
|
} catch {
|
|
@@ -294529,15 +294784,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294529
294784
|
}
|
|
294530
294785
|
const venvDir = getVenvDir();
|
|
294531
294786
|
const isWin2 = process.platform === "win32";
|
|
294532
|
-
const venvBin =
|
|
294533
|
-
const venvMoondream =
|
|
294787
|
+
const venvBin = join76(venvDir, isWin2 ? "Scripts" : "bin");
|
|
294788
|
+
const venvMoondream = join76(venvBin, isWin2 ? "moondream-station.exe" : "moondream-station");
|
|
294534
294789
|
const venv = ensureVenv(log22);
|
|
294535
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
294536
|
-
const venvPip2 =
|
|
294790
|
+
if (venv && !hasCmd("moondream-station") && !existsSync59(venvMoondream)) {
|
|
294791
|
+
const venvPip2 = join76(venvBin, "pip");
|
|
294537
294792
|
log22("Installing moondream-station in ~/.open-agents/venv...");
|
|
294538
294793
|
try {
|
|
294539
294794
|
execSync48(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
294540
|
-
if (
|
|
294795
|
+
if (existsSync59(venvMoondream)) {
|
|
294541
294796
|
log22("moondream-station installed successfully.");
|
|
294542
294797
|
} else {
|
|
294543
294798
|
try {
|
|
@@ -294554,8 +294809,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
294554
294809
|
}
|
|
294555
294810
|
}
|
|
294556
294811
|
if (venv) {
|
|
294557
|
-
const venvPython2 =
|
|
294558
|
-
const venvPip2 =
|
|
294812
|
+
const venvPython2 = join76(venvBin, isWin2 ? "python.exe" : "python");
|
|
294813
|
+
const venvPip2 = join76(venvBin, isWin2 ? "pip.exe" : "pip");
|
|
294559
294814
|
let ocrStackInstalled = false;
|
|
294560
294815
|
try {
|
|
294561
294816
|
execSync48(
|
|
@@ -294611,11 +294866,11 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
294611
294866
|
const cfArch = archMap[arch2] ?? "amd64";
|
|
294612
294867
|
try {
|
|
294613
294868
|
execSync48(
|
|
294614
|
-
`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${
|
|
294869
|
+
`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
294870
|
{ stdio: "pipe", timeout: 6e4 }
|
|
294616
294871
|
);
|
|
294617
|
-
if (!process.env.PATH?.includes(`${
|
|
294618
|
-
process.env.PATH = `${
|
|
294872
|
+
if (!process.env.PATH?.includes(`${homedir26()}/.local/bin`)) {
|
|
294873
|
+
process.env.PATH = `${homedir26()}/.local/bin:${process.env.PATH}`;
|
|
294619
294874
|
}
|
|
294620
294875
|
if (hasCmd("cloudflared")) {
|
|
294621
294876
|
log22("cloudflared installed.");
|
|
@@ -294712,9 +294967,9 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
|
|
|
294712
294967
|
`PARAMETER num_predict ${numPredict}`,
|
|
294713
294968
|
`PARAMETER stop "<|endoftext|>"`
|
|
294714
294969
|
].join("\n");
|
|
294715
|
-
const modelDir2 =
|
|
294970
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294716
294971
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294717
|
-
const modelfilePath =
|
|
294972
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294718
294973
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294719
294974
|
execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
294720
294975
|
stdio: "pipe",
|
|
@@ -294737,9 +294992,9 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
|
|
|
294737
294992
|
`PARAMETER num_predict ${numPredict}`,
|
|
294738
294993
|
`PARAMETER stop "<|endoftext|>"`
|
|
294739
294994
|
].join("\n");
|
|
294740
|
-
const modelDir2 =
|
|
294995
|
+
const modelDir2 = join76(homedir26(), ".open-agents", "models");
|
|
294741
294996
|
mkdirSync33(modelDir2, { recursive: true });
|
|
294742
|
-
const modelfilePath =
|
|
294997
|
+
const modelfilePath = join76(modelDir2, `Modelfile.${customName}`);
|
|
294743
294998
|
writeFileSync30(modelfilePath, modelfileContent + "\n", "utf8");
|
|
294744
294999
|
await execAsync2(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
294745
295000
|
timeout: 12e4
|
|
@@ -294813,8 +295068,8 @@ async function ensureNeovim() {
|
|
|
294813
295068
|
const platform6 = process.platform;
|
|
294814
295069
|
const arch2 = process.arch;
|
|
294815
295070
|
if (platform6 === "linux") {
|
|
294816
|
-
const binDir =
|
|
294817
|
-
const nvimDest =
|
|
295071
|
+
const binDir = join76(homedir26(), ".local", "bin");
|
|
295072
|
+
const nvimDest = join76(binDir, "nvim");
|
|
294818
295073
|
try {
|
|
294819
295074
|
mkdirSync33(binDir, { recursive: true });
|
|
294820
295075
|
} catch {
|
|
@@ -294885,9 +295140,9 @@ async function ensureNeovim() {
|
|
|
294885
295140
|
}
|
|
294886
295141
|
function ensurePathInShellRc(binDir) {
|
|
294887
295142
|
const shell = process.env.SHELL ?? "";
|
|
294888
|
-
const rcFile = shell.includes("zsh") ?
|
|
295143
|
+
const rcFile = shell.includes("zsh") ? join76(homedir26(), ".zshrc") : join76(homedir26(), ".bashrc");
|
|
294889
295144
|
try {
|
|
294890
|
-
const rcContent =
|
|
295145
|
+
const rcContent = existsSync59(rcFile) ? readFileSync46(rcFile, "utf8") : "";
|
|
294891
295146
|
if (rcContent.includes(binDir)) return;
|
|
294892
295147
|
const exportLine = `
|
|
294893
295148
|
export PATH="${binDir}:$PATH" # Added by open-agents for nvim
|
|
@@ -294924,7 +295179,7 @@ var init_setup = __esm({
|
|
|
294924
295179
|
});
|
|
294925
295180
|
|
|
294926
295181
|
// packages/cli/src/tui/drop-panel.ts
|
|
294927
|
-
import { existsSync as
|
|
295182
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
294928
295183
|
import { extname as extname10, resolve as resolve31 } from "node:path";
|
|
294929
295184
|
function ansi4(code8, text) {
|
|
294930
295185
|
return isTTY4 ? `\x1B[${code8}m${text}\x1B[0m` : text;
|
|
@@ -295045,7 +295300,7 @@ function showDropPanel(opts) {
|
|
|
295045
295300
|
filePath = decodeURIComponent(filePath.slice(7));
|
|
295046
295301
|
}
|
|
295047
295302
|
filePath = resolve31(filePath);
|
|
295048
|
-
if (!
|
|
295303
|
+
if (!existsSync60(filePath)) {
|
|
295049
295304
|
errorMsg = `File not found: ${filePath}`;
|
|
295050
295305
|
render2();
|
|
295051
295306
|
return;
|
|
@@ -295117,9 +295372,9 @@ var init_drop_panel = __esm({
|
|
|
295117
295372
|
});
|
|
295118
295373
|
|
|
295119
295374
|
// packages/cli/src/tui/neovim-mode.ts
|
|
295120
|
-
import { existsSync as
|
|
295375
|
+
import { existsSync as existsSync61, unlinkSync as unlinkSync15 } from "node:fs";
|
|
295121
295376
|
import { tmpdir as tmpdir18 } from "node:os";
|
|
295122
|
-
import { join as
|
|
295377
|
+
import { join as join77 } from "node:path";
|
|
295123
295378
|
import { execSync as execSync49 } from "node:child_process";
|
|
295124
295379
|
function isNeovimActive() {
|
|
295125
295380
|
return _state !== null && !_state.cleanedUp;
|
|
@@ -295165,9 +295420,9 @@ async function startNeovimMode(opts) {
|
|
|
295165
295420
|
);
|
|
295166
295421
|
} catch {
|
|
295167
295422
|
}
|
|
295168
|
-
const socketPath =
|
|
295423
|
+
const socketPath = join77(tmpdir18(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
|
|
295169
295424
|
try {
|
|
295170
|
-
if (
|
|
295425
|
+
if (existsSync61(socketPath)) unlinkSync15(socketPath);
|
|
295171
295426
|
} catch {
|
|
295172
295427
|
}
|
|
295173
295428
|
const ptyCols = opts.cols;
|
|
@@ -295414,12 +295669,12 @@ function resizeNeovim(cols, contentRows) {
|
|
|
295414
295669
|
}
|
|
295415
295670
|
async function connectRPC(state, neovimPkg, cols) {
|
|
295416
295671
|
let attempts = 0;
|
|
295417
|
-
while (!
|
|
295672
|
+
while (!existsSync61(state.socketPath) && attempts < 30) {
|
|
295418
295673
|
await new Promise((r2) => setTimeout(r2, 200));
|
|
295419
295674
|
attempts++;
|
|
295420
295675
|
if (state.cleanedUp) return;
|
|
295421
295676
|
}
|
|
295422
|
-
if (!
|
|
295677
|
+
if (!existsSync61(state.socketPath)) return;
|
|
295423
295678
|
const nvim = neovimPkg.attach({ socket: state.socketPath });
|
|
295424
295679
|
state.nvim = nvim;
|
|
295425
295680
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
@@ -295556,7 +295811,7 @@ function doCleanup(state) {
|
|
|
295556
295811
|
state.pty = null;
|
|
295557
295812
|
}
|
|
295558
295813
|
try {
|
|
295559
|
-
if (
|
|
295814
|
+
if (existsSync61(state.socketPath)) unlinkSync15(state.socketPath);
|
|
295560
295815
|
} catch {
|
|
295561
295816
|
}
|
|
295562
295817
|
if (state.stdinHandler) {
|
|
@@ -295626,9 +295881,9 @@ __export(daemon_exports, {
|
|
|
295626
295881
|
stopDaemon: () => stopDaemon
|
|
295627
295882
|
});
|
|
295628
295883
|
import { spawn as spawn23 } from "node:child_process";
|
|
295629
|
-
import { existsSync as
|
|
295630
|
-
import { join as
|
|
295631
|
-
import { homedir as
|
|
295884
|
+
import { existsSync as existsSync62, readFileSync as readFileSync47, writeFileSync as writeFileSync31, mkdirSync as mkdirSync34, unlinkSync as unlinkSync16 } from "node:fs";
|
|
295885
|
+
import { join as join78 } from "node:path";
|
|
295886
|
+
import { homedir as homedir27 } from "node:os";
|
|
295632
295887
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
295633
295888
|
import { dirname as dirname22 } from "node:path";
|
|
295634
295889
|
function getDaemonPort() {
|
|
@@ -295652,9 +295907,9 @@ async function isDaemonRunning(port) {
|
|
|
295652
295907
|
}
|
|
295653
295908
|
}
|
|
295654
295909
|
function getDaemonPid() {
|
|
295655
|
-
if (!
|
|
295910
|
+
if (!existsSync62(PID_FILE2)) return null;
|
|
295656
295911
|
try {
|
|
295657
|
-
const pid = parseInt(
|
|
295912
|
+
const pid = parseInt(readFileSync47(PID_FILE2, "utf8").trim(), 10);
|
|
295658
295913
|
if (!pid || pid <= 0) return null;
|
|
295659
295914
|
process.kill(pid, 0);
|
|
295660
295915
|
return pid;
|
|
@@ -295680,8 +295935,8 @@ async function startDaemon() {
|
|
|
295680
295935
|
}
|
|
295681
295936
|
if (!oaScript) {
|
|
295682
295937
|
const thisDir = dirname22(fileURLToPath13(import.meta.url));
|
|
295683
|
-
const indexJs =
|
|
295684
|
-
if (
|
|
295938
|
+
const indexJs = join78(thisDir, "index.js");
|
|
295939
|
+
if (existsSync62(indexJs)) oaScript = indexJs;
|
|
295685
295940
|
}
|
|
295686
295941
|
if (!oaScript) return null;
|
|
295687
295942
|
try {
|
|
@@ -295779,8 +296034,8 @@ var OA_DIR2, PID_FILE2, DEFAULT_PORT2;
|
|
|
295779
296034
|
var init_daemon = __esm({
|
|
295780
296035
|
"packages/cli/src/daemon.ts"() {
|
|
295781
296036
|
"use strict";
|
|
295782
|
-
OA_DIR2 =
|
|
295783
|
-
PID_FILE2 =
|
|
296037
|
+
OA_DIR2 = join78(homedir27(), ".open-agents");
|
|
296038
|
+
PID_FILE2 = join78(OA_DIR2, "daemon.pid");
|
|
295784
296039
|
DEFAULT_PORT2 = 11435;
|
|
295785
296040
|
}
|
|
295786
296041
|
});
|
|
@@ -296165,8 +296420,8 @@ __export(sponsor_wizard_exports, {
|
|
|
296165
296420
|
saveSponsorConfig: () => saveSponsorConfig,
|
|
296166
296421
|
showSponsorDashboard: () => showSponsorDashboard
|
|
296167
296422
|
});
|
|
296168
|
-
import { existsSync as
|
|
296169
|
-
import { join as
|
|
296423
|
+
import { existsSync as existsSync63, readFileSync as readFileSync48, writeFileSync as writeFileSync32, mkdirSync as mkdirSync35 } from "node:fs";
|
|
296424
|
+
import { join as join79 } from "node:path";
|
|
296170
296425
|
function colorPreview(code8) {
|
|
296171
296426
|
return `\x1B[38;5;${code8}m████\x1B[0m (${code8})`;
|
|
296172
296427
|
}
|
|
@@ -296179,16 +296434,16 @@ function gradientPreview(start2, end) {
|
|
|
296179
296434
|
return s2;
|
|
296180
296435
|
}
|
|
296181
296436
|
function sponsorDir(projectDir) {
|
|
296182
|
-
return
|
|
296437
|
+
return join79(projectDir, ".oa", "sponsor");
|
|
296183
296438
|
}
|
|
296184
296439
|
function configPath(projectDir) {
|
|
296185
|
-
return
|
|
296440
|
+
return join79(sponsorDir(projectDir), "config.json");
|
|
296186
296441
|
}
|
|
296187
296442
|
function loadSponsorConfig(projectDir) {
|
|
296188
296443
|
const p2 = configPath(projectDir);
|
|
296189
|
-
if (!
|
|
296444
|
+
if (!existsSync63(p2)) return null;
|
|
296190
296445
|
try {
|
|
296191
|
-
return JSON.parse(
|
|
296446
|
+
return JSON.parse(readFileSync48(p2, "utf8"));
|
|
296192
296447
|
} catch {
|
|
296193
296448
|
return null;
|
|
296194
296449
|
}
|
|
@@ -297077,9 +297332,9 @@ __export(voice_exports, {
|
|
|
297077
297332
|
registerCustomOnnxModel: () => registerCustomOnnxModel,
|
|
297078
297333
|
resetNarrationContext: () => resetNarrationContext
|
|
297079
297334
|
});
|
|
297080
|
-
import { existsSync as
|
|
297081
|
-
import { join as
|
|
297082
|
-
import { homedir as
|
|
297335
|
+
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";
|
|
297336
|
+
import { join as join80, dirname as dirname23 } from "node:path";
|
|
297337
|
+
import { homedir as homedir28, tmpdir as tmpdir19, platform as platform4 } from "node:os";
|
|
297083
297338
|
import { execSync as execSync50, spawn as nodeSpawn } from "node:child_process";
|
|
297084
297339
|
import { createRequire as createRequire3 } from "node:module";
|
|
297085
297340
|
function sanitizeForTTS(text) {
|
|
@@ -297103,37 +297358,37 @@ function listVoiceModels() {
|
|
|
297103
297358
|
}));
|
|
297104
297359
|
}
|
|
297105
297360
|
function voiceDir() {
|
|
297106
|
-
return
|
|
297361
|
+
return join80(homedir28(), ".open-agents", "voice");
|
|
297107
297362
|
}
|
|
297108
297363
|
function modelsDir() {
|
|
297109
|
-
return
|
|
297364
|
+
return join80(voiceDir(), "models");
|
|
297110
297365
|
}
|
|
297111
297366
|
function modelDir(id) {
|
|
297112
|
-
return
|
|
297367
|
+
return join80(modelsDir(), id);
|
|
297113
297368
|
}
|
|
297114
297369
|
function modelOnnxPath(id) {
|
|
297115
|
-
return
|
|
297370
|
+
return join80(modelDir(id), "model.onnx");
|
|
297116
297371
|
}
|
|
297117
297372
|
function modelConfigPath(id) {
|
|
297118
|
-
return
|
|
297373
|
+
return join80(modelDir(id), "config.json");
|
|
297119
297374
|
}
|
|
297120
297375
|
function luxttsVenvDir() {
|
|
297121
|
-
return
|
|
297376
|
+
return join80(voiceDir(), "luxtts-venv");
|
|
297122
297377
|
}
|
|
297123
297378
|
function luxttsVenvPy() {
|
|
297124
|
-
return platform4() === "win32" ?
|
|
297379
|
+
return platform4() === "win32" ? join80(luxttsVenvDir(), "Scripts", "python.exe") : join80(luxttsVenvDir(), "bin", "python3");
|
|
297125
297380
|
}
|
|
297126
297381
|
function luxttsRepoDir() {
|
|
297127
|
-
return
|
|
297382
|
+
return join80(voiceDir(), "LuxTTS");
|
|
297128
297383
|
}
|
|
297129
297384
|
function luxttsCloneRefsDir() {
|
|
297130
|
-
return
|
|
297385
|
+
return join80(voiceDir(), "clone-refs");
|
|
297131
297386
|
}
|
|
297132
297387
|
function luxttsInferScript() {
|
|
297133
|
-
return
|
|
297388
|
+
return join80(voiceDir(), "luxtts-infer.py");
|
|
297134
297389
|
}
|
|
297135
297390
|
function writeDetectTorchScript(targetPath) {
|
|
297136
|
-
if (
|
|
297391
|
+
if (existsSync64(targetPath)) return;
|
|
297137
297392
|
try {
|
|
297138
297393
|
mkdirSync36(dirname23(targetPath), { recursive: true });
|
|
297139
297394
|
} catch {
|
|
@@ -297958,8 +298213,8 @@ var init_voice = __esm({
|
|
|
297958
298213
|
const refsDir = luxttsCloneRefsDir();
|
|
297959
298214
|
const targets = ["glados", "overwatch"];
|
|
297960
298215
|
for (const modelId of targets) {
|
|
297961
|
-
const refFile =
|
|
297962
|
-
if (
|
|
298216
|
+
const refFile = join80(refsDir, `${modelId}-ref.wav`);
|
|
298217
|
+
if (existsSync64(refFile)) continue;
|
|
297963
298218
|
try {
|
|
297964
298219
|
await this.generateCloneRef(modelId);
|
|
297965
298220
|
const meta = this.loadCloneMeta();
|
|
@@ -298035,22 +298290,22 @@ var init_voice = __esm({
|
|
|
298035
298290
|
}
|
|
298036
298291
|
p2 = p2.replace(/\\ /g, " ");
|
|
298037
298292
|
if (p2.startsWith("~/") || p2 === "~") {
|
|
298038
|
-
p2 =
|
|
298293
|
+
p2 = join80(homedir28(), p2.slice(1));
|
|
298039
298294
|
}
|
|
298040
|
-
if (!
|
|
298295
|
+
if (!existsSync64(p2)) {
|
|
298041
298296
|
return `File not found: ${p2}
|
|
298042
298297
|
(original input: ${audioPath})`;
|
|
298043
298298
|
}
|
|
298044
298299
|
audioPath = p2;
|
|
298045
298300
|
const refsDir = luxttsCloneRefsDir();
|
|
298046
|
-
if (!
|
|
298301
|
+
if (!existsSync64(refsDir)) mkdirSync36(refsDir, { recursive: true });
|
|
298047
298302
|
const ext = audioPath.split(".").pop() || "wav";
|
|
298048
298303
|
const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
298049
298304
|
const ts = Date.now().toString(36);
|
|
298050
298305
|
const destFilename = `clone-${srcName}-${ts}.${ext}`;
|
|
298051
|
-
const destPath =
|
|
298306
|
+
const destPath = join80(refsDir, destFilename);
|
|
298052
298307
|
try {
|
|
298053
|
-
const data =
|
|
298308
|
+
const data = readFileSync49(audioPath);
|
|
298054
298309
|
writeFileSync33(destPath, data);
|
|
298055
298310
|
} catch (err) {
|
|
298056
298311
|
return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
|
|
@@ -298091,8 +298346,8 @@ var init_voice = __esm({
|
|
|
298091
298346
|
return `Failed to synthesize reference audio from ${source.label}.`;
|
|
298092
298347
|
}
|
|
298093
298348
|
const refsDir = luxttsCloneRefsDir();
|
|
298094
|
-
if (!
|
|
298095
|
-
const destPath =
|
|
298349
|
+
if (!existsSync64(refsDir)) mkdirSync36(refsDir, { recursive: true });
|
|
298350
|
+
const destPath = join80(refsDir, `${sourceModelId}-ref.wav`);
|
|
298096
298351
|
const sampleRate = this.config?.audio?.sample_rate ?? 22050;
|
|
298097
298352
|
this.writeWav(audioData, sampleRate, destPath);
|
|
298098
298353
|
this.luxttsCloneRef = destPath;
|
|
@@ -298108,20 +298363,20 @@ var init_voice = __esm({
|
|
|
298108
298363
|
// -------------------------------------------------------------------------
|
|
298109
298364
|
/** Metadata file for friendly names of clone refs */
|
|
298110
298365
|
static cloneMetaFile() {
|
|
298111
|
-
return
|
|
298366
|
+
return join80(luxttsCloneRefsDir(), "meta.json");
|
|
298112
298367
|
}
|
|
298113
298368
|
loadCloneMeta() {
|
|
298114
298369
|
const p2 = _VoiceEngine.cloneMetaFile();
|
|
298115
|
-
if (!
|
|
298370
|
+
if (!existsSync64(p2)) return {};
|
|
298116
298371
|
try {
|
|
298117
|
-
return JSON.parse(
|
|
298372
|
+
return JSON.parse(readFileSync49(p2, "utf8"));
|
|
298118
298373
|
} catch {
|
|
298119
298374
|
return {};
|
|
298120
298375
|
}
|
|
298121
298376
|
}
|
|
298122
298377
|
saveCloneMeta(meta) {
|
|
298123
298378
|
const dir = luxttsCloneRefsDir();
|
|
298124
|
-
if (!
|
|
298379
|
+
if (!existsSync64(dir)) mkdirSync36(dir, { recursive: true });
|
|
298125
298380
|
writeFileSync33(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
|
|
298126
298381
|
}
|
|
298127
298382
|
/** Audio file extensions recognized as clone references */
|
|
@@ -298132,14 +298387,14 @@ var init_voice = __esm({
|
|
|
298132
298387
|
*/
|
|
298133
298388
|
listCloneRefs() {
|
|
298134
298389
|
const dir = luxttsCloneRefsDir();
|
|
298135
|
-
if (!
|
|
298390
|
+
if (!existsSync64(dir)) return [];
|
|
298136
298391
|
const meta = this.loadCloneMeta();
|
|
298137
298392
|
const files = readdirSync16(dir).filter((f2) => {
|
|
298138
298393
|
const ext = f2.split(".").pop()?.toLowerCase() ?? "";
|
|
298139
298394
|
return _VoiceEngine.AUDIO_EXTS.has(ext);
|
|
298140
298395
|
});
|
|
298141
298396
|
return files.map((f2) => {
|
|
298142
|
-
const p2 =
|
|
298397
|
+
const p2 = join80(dir, f2);
|
|
298143
298398
|
let size = 0;
|
|
298144
298399
|
try {
|
|
298145
298400
|
size = statSync18(p2).size;
|
|
@@ -298156,8 +298411,8 @@ var init_voice = __esm({
|
|
|
298156
298411
|
}
|
|
298157
298412
|
/** Delete a clone reference file by filename. Returns true if deleted. */
|
|
298158
298413
|
deleteCloneRef(filename) {
|
|
298159
|
-
const p2 =
|
|
298160
|
-
if (!
|
|
298414
|
+
const p2 = join80(luxttsCloneRefsDir(), filename);
|
|
298415
|
+
if (!existsSync64(p2)) return false;
|
|
298161
298416
|
try {
|
|
298162
298417
|
unlinkSync17(p2);
|
|
298163
298418
|
const meta = this.loadCloneMeta();
|
|
@@ -298180,8 +298435,8 @@ var init_voice = __esm({
|
|
|
298180
298435
|
}
|
|
298181
298436
|
/** Set the active clone reference by filename. */
|
|
298182
298437
|
setActiveCloneRef(filename) {
|
|
298183
|
-
const p2 =
|
|
298184
|
-
if (!
|
|
298438
|
+
const p2 = join80(luxttsCloneRefsDir(), filename);
|
|
298439
|
+
if (!existsSync64(p2)) return `File not found: ${filename}`;
|
|
298185
298440
|
this.luxttsCloneRef = p2;
|
|
298186
298441
|
return `Active clone voice set to: ${filename}`;
|
|
298187
298442
|
}
|
|
@@ -298518,7 +298773,7 @@ var init_voice = __esm({
|
|
|
298518
298773
|
}
|
|
298519
298774
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
298520
298775
|
}
|
|
298521
|
-
const wavPath =
|
|
298776
|
+
const wavPath = join80(tmpdir19(), `oa-voice-${Date.now()}.wav`);
|
|
298522
298777
|
this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
|
|
298523
298778
|
await this.playWav(wavPath);
|
|
298524
298779
|
try {
|
|
@@ -298914,7 +299169,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298914
299169
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
298915
299170
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
298916
299171
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
298917
|
-
const wavPath =
|
|
299172
|
+
const wavPath = join80(tmpdir19(), `oa-mlx-${Date.now()}.wav`);
|
|
298918
299173
|
const pyScript = [
|
|
298919
299174
|
"import sys, json",
|
|
298920
299175
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -298937,10 +299192,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298937
299192
|
return;
|
|
298938
299193
|
}
|
|
298939
299194
|
}
|
|
298940
|
-
if (!
|
|
299195
|
+
if (!existsSync64(wavPath)) return;
|
|
298941
299196
|
if (volume !== 1) {
|
|
298942
299197
|
try {
|
|
298943
|
-
const wavData =
|
|
299198
|
+
const wavData = readFileSync49(wavPath);
|
|
298944
299199
|
if (wavData.length > 44) {
|
|
298945
299200
|
const header = wavData.subarray(0, 44);
|
|
298946
299201
|
const samples = new Int16Array(
|
|
@@ -298959,7 +299214,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298959
299214
|
}
|
|
298960
299215
|
if (this.onPCMOutput) {
|
|
298961
299216
|
try {
|
|
298962
|
-
const wavData =
|
|
299217
|
+
const wavData = readFileSync49(wavPath);
|
|
298963
299218
|
if (wavData.length > 44) {
|
|
298964
299219
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
298965
299220
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -298988,7 +299243,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
298988
299243
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
298989
299244
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
298990
299245
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
298991
|
-
const wavPath =
|
|
299246
|
+
const wavPath = join80(tmpdir19(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
298992
299247
|
const pyScript = [
|
|
298993
299248
|
"import sys, json",
|
|
298994
299249
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -299011,9 +299266,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299011
299266
|
return null;
|
|
299012
299267
|
}
|
|
299013
299268
|
}
|
|
299014
|
-
if (!
|
|
299269
|
+
if (!existsSync64(wavPath)) return null;
|
|
299015
299270
|
try {
|
|
299016
|
-
const data =
|
|
299271
|
+
const data = readFileSync49(wavPath);
|
|
299017
299272
|
unlinkSync17(wavPath);
|
|
299018
299273
|
return data;
|
|
299019
299274
|
} catch {
|
|
@@ -299038,7 +299293,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299038
299293
|
}
|
|
299039
299294
|
const venvDir = luxttsVenvDir();
|
|
299040
299295
|
const venvPy = luxttsVenvPy();
|
|
299041
|
-
if (
|
|
299296
|
+
if (existsSync64(venvPy)) {
|
|
299042
299297
|
try {
|
|
299043
299298
|
const quotedPy = `"${venvPy}"`;
|
|
299044
299299
|
const repoPath = luxttsRepoDir().replace(/\\/g, "/");
|
|
@@ -299060,7 +299315,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299060
299315
|
if (torchCheck === "cpu") {
|
|
299061
299316
|
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
|
|
299062
299317
|
try {
|
|
299063
|
-
const detectScript =
|
|
299318
|
+
const detectScript = join80(voiceDir(), "detect-torch.py");
|
|
299064
299319
|
writeDetectTorchScript(detectScript);
|
|
299065
299320
|
let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
|
|
299066
299321
|
try {
|
|
@@ -299087,7 +299342,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299087
299342
|
}
|
|
299088
299343
|
}
|
|
299089
299344
|
renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
|
|
299090
|
-
if (!
|
|
299345
|
+
if (!existsSync64(venvDir)) {
|
|
299091
299346
|
renderInfo(" Creating Python virtual environment...");
|
|
299092
299347
|
try {
|
|
299093
299348
|
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
@@ -299098,7 +299353,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299098
299353
|
}
|
|
299099
299354
|
}
|
|
299100
299355
|
{
|
|
299101
|
-
const detectScript =
|
|
299356
|
+
const detectScript = join80(voiceDir(), "detect-torch.py");
|
|
299102
299357
|
writeDetectTorchScript(detectScript);
|
|
299103
299358
|
let pipArgsStr = "torch torchaudio";
|
|
299104
299359
|
let torchDesc = "unknown platform";
|
|
@@ -299143,10 +299398,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299143
299398
|
}
|
|
299144
299399
|
}
|
|
299145
299400
|
const repoDir = luxttsRepoDir();
|
|
299146
|
-
if (!
|
|
299401
|
+
if (!existsSync64(join80(repoDir, "zipvoice", "luxvoice.py"))) {
|
|
299147
299402
|
renderInfo(" Cloning LuxTTS repository...");
|
|
299148
299403
|
try {
|
|
299149
|
-
if (
|
|
299404
|
+
if (existsSync64(repoDir)) {
|
|
299150
299405
|
const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
|
|
299151
299406
|
await this.asyncShell(rmCmd, 3e4);
|
|
299152
299407
|
}
|
|
@@ -299235,7 +299490,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299235
299490
|
renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
|
|
299236
299491
|
}
|
|
299237
299492
|
}
|
|
299238
|
-
const isJetson = isArm && (
|
|
299493
|
+
const isJetson = isArm && (existsSync64("/etc/nv_tegra_release") || existsSync64("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
|
|
299239
299494
|
const installSteps = isArm ? [
|
|
299240
299495
|
// ARM: install individually so we get clear error messages per package.
|
|
299241
299496
|
// ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
|
|
@@ -299248,7 +299503,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299248
299503
|
...isJetson ? (() => {
|
|
299249
299504
|
let jpVer = "v60";
|
|
299250
299505
|
try {
|
|
299251
|
-
const tegra =
|
|
299506
|
+
const tegra = existsSync64("/etc/nv_tegra_release") ? execSync50("cat /etc/nv_tegra_release 2>/dev/null", { encoding: "utf8", timeout: 3e3 }).trim() : "";
|
|
299252
299507
|
const dpkg = execSync50("dpkg -l nvidia-jetpack 2>/dev/null | grep nvidia-jetpack | awk '{print $3}'", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
299253
299508
|
const ver = dpkg || process.env.JETSON_L4T_VERSION || "";
|
|
299254
299509
|
if (ver.startsWith("5.") || tegra.includes("R35") || tegra.includes("R34")) jpVer = "v51";
|
|
@@ -299328,12 +299583,12 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
|
299328
299583
|
}
|
|
299329
299584
|
/** Auto-detect an existing clone reference in the refs directory */
|
|
299330
299585
|
autoDetectCloneRef() {
|
|
299331
|
-
if (this.luxttsCloneRef &&
|
|
299586
|
+
if (this.luxttsCloneRef && existsSync64(this.luxttsCloneRef)) return;
|
|
299332
299587
|
const refsDir = luxttsCloneRefsDir();
|
|
299333
|
-
if (!
|
|
299588
|
+
if (!existsSync64(refsDir)) return;
|
|
299334
299589
|
for (const name10 of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
|
|
299335
|
-
const p2 =
|
|
299336
|
-
if (
|
|
299590
|
+
const p2 = join80(refsDir, name10);
|
|
299591
|
+
if (existsSync64(p2)) {
|
|
299337
299592
|
this.luxttsCloneRef = p2;
|
|
299338
299593
|
return;
|
|
299339
299594
|
}
|
|
@@ -299440,7 +299695,7 @@ if __name__ == '__main__':
|
|
|
299440
299695
|
async ensureLuxttsDaemon() {
|
|
299441
299696
|
if (this._luxttsDaemon && !this._luxttsDaemon.killed) return true;
|
|
299442
299697
|
const venvPy = luxttsVenvPy();
|
|
299443
|
-
if (!
|
|
299698
|
+
if (!existsSync64(venvPy)) return false;
|
|
299444
299699
|
return new Promise((resolve39) => {
|
|
299445
299700
|
const env2 = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
299446
299701
|
const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
|
|
@@ -299529,12 +299784,12 @@ if __name__ == '__main__':
|
|
|
299529
299784
|
* Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
|
|
299530
299785
|
*/
|
|
299531
299786
|
async synthesizeLuxttsWav(text, speedFactor = 1) {
|
|
299532
|
-
if (!this.luxttsCloneRef || !
|
|
299787
|
+
if (!this.luxttsCloneRef || !existsSync64(this.luxttsCloneRef)) return null;
|
|
299533
299788
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
299534
299789
|
if (!cleaned) return null;
|
|
299535
299790
|
const ready = await this.ensureLuxttsDaemon();
|
|
299536
299791
|
if (!ready) return null;
|
|
299537
|
-
const wavPath =
|
|
299792
|
+
const wavPath = join80(tmpdir19(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
|
|
299538
299793
|
try {
|
|
299539
299794
|
await this.luxttsRequest({
|
|
299540
299795
|
action: "synthesize",
|
|
@@ -299546,16 +299801,16 @@ if __name__ == '__main__':
|
|
|
299546
299801
|
} catch {
|
|
299547
299802
|
return null;
|
|
299548
299803
|
}
|
|
299549
|
-
return
|
|
299804
|
+
return existsSync64(wavPath) ? wavPath : null;
|
|
299550
299805
|
}
|
|
299551
299806
|
/**
|
|
299552
299807
|
* Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
|
|
299553
299808
|
* Cleans up the WAV file after playback.
|
|
299554
299809
|
*/
|
|
299555
299810
|
async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
|
|
299556
|
-
if (!
|
|
299811
|
+
if (!existsSync64(wavPath)) return;
|
|
299557
299812
|
try {
|
|
299558
|
-
const wavData =
|
|
299813
|
+
const wavData = readFileSync49(wavPath);
|
|
299559
299814
|
if (wavData.length > 44) {
|
|
299560
299815
|
const sampleRate = wavData.readUInt32LE(24);
|
|
299561
299816
|
const samples = new Int16Array(
|
|
@@ -299580,7 +299835,7 @@ if __name__ == '__main__':
|
|
|
299580
299835
|
}
|
|
299581
299836
|
if (pitchFactor !== 1) {
|
|
299582
299837
|
try {
|
|
299583
|
-
const wavData =
|
|
299838
|
+
const wavData = readFileSync49(wavPath);
|
|
299584
299839
|
if (wavData.length > 44) {
|
|
299585
299840
|
const int16 = new Int16Array(
|
|
299586
299841
|
wavData.buffer,
|
|
@@ -299599,7 +299854,7 @@ if __name__ == '__main__':
|
|
|
299599
299854
|
}
|
|
299600
299855
|
if (this.onPCMOutput) {
|
|
299601
299856
|
try {
|
|
299602
|
-
const wavData =
|
|
299857
|
+
const wavData = readFileSync49(wavPath);
|
|
299603
299858
|
if (wavData.length > 44) {
|
|
299604
299859
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
299605
299860
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -299610,7 +299865,7 @@ if __name__ == '__main__':
|
|
|
299610
299865
|
}
|
|
299611
299866
|
if (stereoDelayMs > 0) {
|
|
299612
299867
|
try {
|
|
299613
|
-
const wavData =
|
|
299868
|
+
const wavData = readFileSync49(wavPath);
|
|
299614
299869
|
if (wavData.length > 44) {
|
|
299615
299870
|
const sampleRate = wavData.readUInt32LE(24);
|
|
299616
299871
|
const numChannels = wavData.readUInt16LE(22);
|
|
@@ -299649,12 +299904,12 @@ if __name__ == '__main__':
|
|
|
299649
299904
|
* Used for Telegram voice messages and WebSocket streaming.
|
|
299650
299905
|
*/
|
|
299651
299906
|
async synthesizeLuxttsToBuffer(text) {
|
|
299652
|
-
if (!this.luxttsCloneRef || !
|
|
299907
|
+
if (!this.luxttsCloneRef || !existsSync64(this.luxttsCloneRef)) return null;
|
|
299653
299908
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
299654
299909
|
if (!cleaned) return null;
|
|
299655
299910
|
const ready = await this.ensureLuxttsDaemon();
|
|
299656
299911
|
if (!ready) return null;
|
|
299657
|
-
const wavPath =
|
|
299912
|
+
const wavPath = join80(tmpdir19(), `oa-luxtts-buf-${Date.now()}.wav`);
|
|
299658
299913
|
try {
|
|
299659
299914
|
await this.luxttsRequest({
|
|
299660
299915
|
action: "synthesize",
|
|
@@ -299666,9 +299921,9 @@ if __name__ == '__main__':
|
|
|
299666
299921
|
} catch {
|
|
299667
299922
|
return null;
|
|
299668
299923
|
}
|
|
299669
|
-
if (!
|
|
299924
|
+
if (!existsSync64(wavPath)) return null;
|
|
299670
299925
|
try {
|
|
299671
|
-
const data =
|
|
299926
|
+
const data = readFileSync49(wavPath);
|
|
299672
299927
|
unlinkSync17(wavPath);
|
|
299673
299928
|
return data;
|
|
299674
299929
|
} catch {
|
|
@@ -299682,14 +299937,14 @@ if __name__ == '__main__':
|
|
|
299682
299937
|
if (this.ort) return;
|
|
299683
299938
|
const arch2 = process.arch;
|
|
299684
299939
|
mkdirSync36(voiceDir(), { recursive: true });
|
|
299685
|
-
const pkgPath =
|
|
299940
|
+
const pkgPath = join80(voiceDir(), "package.json");
|
|
299686
299941
|
const expectedDeps = {
|
|
299687
299942
|
"onnxruntime-node": "^1.21.0",
|
|
299688
299943
|
"phonemizer": "^1.2.1"
|
|
299689
299944
|
};
|
|
299690
|
-
if (
|
|
299945
|
+
if (existsSync64(pkgPath)) {
|
|
299691
299946
|
try {
|
|
299692
|
-
const existing = JSON.parse(
|
|
299947
|
+
const existing = JSON.parse(readFileSync49(pkgPath, "utf8"));
|
|
299693
299948
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
299694
299949
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
299695
299950
|
writeFileSync33(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -299697,18 +299952,18 @@ if __name__ == '__main__':
|
|
|
299697
299952
|
} catch {
|
|
299698
299953
|
}
|
|
299699
299954
|
}
|
|
299700
|
-
if (!
|
|
299955
|
+
if (!existsSync64(pkgPath)) {
|
|
299701
299956
|
writeFileSync33(pkgPath, JSON.stringify({
|
|
299702
299957
|
name: "open-agents-voice",
|
|
299703
299958
|
private: true,
|
|
299704
299959
|
dependencies: expectedDeps
|
|
299705
299960
|
}, null, 2));
|
|
299706
299961
|
}
|
|
299707
|
-
const voiceRequire = createRequire3(
|
|
299962
|
+
const voiceRequire = createRequire3(join80(voiceDir(), "index.js"));
|
|
299708
299963
|
const probeOnnx = async () => {
|
|
299709
299964
|
try {
|
|
299710
299965
|
const output = await this.asyncShell(
|
|
299711
|
-
`NODE_PATH="${
|
|
299966
|
+
`NODE_PATH="${join80(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`,
|
|
299712
299967
|
15e3
|
|
299713
299968
|
);
|
|
299714
299969
|
return output.trim() === "OK";
|
|
@@ -299716,8 +299971,8 @@ if __name__ == '__main__':
|
|
|
299716
299971
|
return false;
|
|
299717
299972
|
}
|
|
299718
299973
|
};
|
|
299719
|
-
const onnxNodeModules =
|
|
299720
|
-
const onnxInstalled =
|
|
299974
|
+
const onnxNodeModules = join80(voiceDir(), "node_modules", "onnxruntime-node");
|
|
299975
|
+
const onnxInstalled = existsSync64(onnxNodeModules);
|
|
299721
299976
|
if (onnxInstalled && !await probeOnnx()) {
|
|
299722
299977
|
throw new Error(
|
|
299723
299978
|
`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 +300031,16 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299776
300031
|
const dir = modelDir(id);
|
|
299777
300032
|
const onnxPath = modelOnnxPath(id);
|
|
299778
300033
|
const configPath2 = modelConfigPath(id);
|
|
299779
|
-
if (
|
|
300034
|
+
if (existsSync64(onnxPath) && existsSync64(configPath2)) return;
|
|
299780
300035
|
mkdirSync36(dir, { recursive: true });
|
|
299781
|
-
if (!
|
|
300036
|
+
if (!existsSync64(configPath2)) {
|
|
299782
300037
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
299783
300038
|
const configResp = await fetch(model.configUrl);
|
|
299784
300039
|
if (!configResp.ok) throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
299785
300040
|
const configText = await configResp.text();
|
|
299786
300041
|
writeFileSync33(configPath2, configText);
|
|
299787
300042
|
}
|
|
299788
|
-
if (!
|
|
300043
|
+
if (!existsSync64(onnxPath)) {
|
|
299789
300044
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
299790
300045
|
const onnxResp = await fetch(model.onnxUrl);
|
|
299791
300046
|
if (!onnxResp.ok) throw new Error(`Failed to download model: HTTP ${onnxResp.status}`);
|
|
@@ -299818,10 +300073,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299818
300073
|
if (!this.ort) throw new Error("ONNX runtime not loaded");
|
|
299819
300074
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
299820
300075
|
const configPath2 = modelConfigPath(this.modelId);
|
|
299821
|
-
if (!
|
|
300076
|
+
if (!existsSync64(onnxPath) || !existsSync64(configPath2)) {
|
|
299822
300077
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
299823
300078
|
}
|
|
299824
|
-
this.config = JSON.parse(
|
|
300079
|
+
this.config = JSON.parse(readFileSync49(configPath2, "utf8"));
|
|
299825
300080
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
299826
300081
|
executionProviders: ["cpu"],
|
|
299827
300082
|
graphOptimizationLevel: "all"
|
|
@@ -299848,8 +300103,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
299848
300103
|
// packages/cli/src/tui/commands.ts
|
|
299849
300104
|
import * as nodeOs from "node:os";
|
|
299850
300105
|
import { execSync as nodeExecSync } from "node:child_process";
|
|
299851
|
-
import { existsSync as
|
|
299852
|
-
import { join as
|
|
300106
|
+
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";
|
|
300107
|
+
import { join as join81 } from "node:path";
|
|
299853
300108
|
async function _immediateReregister(newUrl) {
|
|
299854
300109
|
if (!_lastRegisteredSponsorPayload) return;
|
|
299855
300110
|
_lastRegisteredSponsorPayload.tunnelUrl = newUrl;
|
|
@@ -300362,9 +300617,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300362
300617
|
if (out.includes("Connected") || out.includes("Already connected")) {
|
|
300363
300618
|
renderInfo(out.split("\n").slice(0, 4).join("\n"));
|
|
300364
300619
|
try {
|
|
300365
|
-
const pidFile =
|
|
300366
|
-
if (
|
|
300367
|
-
const pid = parseInt(
|
|
300620
|
+
const pidFile = join81(ctx3.repoRoot ?? process.cwd(), ".oa", "nexus", "daemon.pid");
|
|
300621
|
+
if (existsSync65(pidFile)) {
|
|
300622
|
+
const pid = parseInt(readFileSync50(pidFile, "utf8").trim(), 10);
|
|
300368
300623
|
if (pid > 0 && !registry2.daemons.has("Nexus")) {
|
|
300369
300624
|
registry2.register({ name: "Nexus", pid, startedAt: Date.now(), status: "running" });
|
|
300370
300625
|
}
|
|
@@ -300668,22 +300923,22 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300668
300923
|
let content = "";
|
|
300669
300924
|
let metadata = {};
|
|
300670
300925
|
if (shareType === "tool") {
|
|
300671
|
-
const toolDir =
|
|
300672
|
-
const toolFile =
|
|
300673
|
-
if (!
|
|
300926
|
+
const toolDir = join81(ctx3.repoRoot, ".oa", "tools");
|
|
300927
|
+
const toolFile = join81(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
|
|
300928
|
+
if (!existsSync65(toolFile)) {
|
|
300674
300929
|
renderWarning(`Tool not found: ${toolFile}`);
|
|
300675
300930
|
return "handled";
|
|
300676
300931
|
}
|
|
300677
|
-
content =
|
|
300932
|
+
content = readFileSync50(toolFile, "utf8");
|
|
300678
300933
|
metadata = { type: "tool", name: shareName };
|
|
300679
300934
|
} else if (shareType === "skill") {
|
|
300680
|
-
const skillDir =
|
|
300681
|
-
const skillFile =
|
|
300682
|
-
if (!
|
|
300935
|
+
const skillDir = join81(ctx3.repoRoot, ".oa", "skills", shareName);
|
|
300936
|
+
const skillFile = join81(skillDir, "SKILL.md");
|
|
300937
|
+
if (!existsSync65(skillFile)) {
|
|
300683
300938
|
renderWarning(`Skill not found: ${skillFile}`);
|
|
300684
300939
|
return "handled";
|
|
300685
300940
|
}
|
|
300686
|
-
content =
|
|
300941
|
+
content = readFileSync50(skillFile, "utf8");
|
|
300687
300942
|
metadata = { type: "skill", name: shareName };
|
|
300688
300943
|
} else {
|
|
300689
300944
|
renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
|
|
@@ -300720,9 +300975,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300720
300975
|
try {
|
|
300721
300976
|
const nexus = new NexusTool(ctx3.repoRoot);
|
|
300722
300977
|
await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
|
|
300723
|
-
const regFile =
|
|
300724
|
-
if (
|
|
300725
|
-
const reg = JSON.parse(
|
|
300978
|
+
const regFile = join81(ctx3.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
|
|
300979
|
+
if (existsSync65(regFile)) {
|
|
300980
|
+
const reg = JSON.parse(readFileSync50(regFile, "utf8"));
|
|
300726
300981
|
const pinned = Object.values(reg).some((e2) => e2.cid === importCid && e2.pinned);
|
|
300727
300982
|
if (pinned) {
|
|
300728
300983
|
renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
|
|
@@ -300773,32 +301028,32 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300773
301028
|
lines.push(`
|
|
300774
301029
|
${c3.bold("IPFS / Helia Status")}
|
|
300775
301030
|
`);
|
|
300776
|
-
const ipfsDir =
|
|
300777
|
-
const ipfsLocalDir =
|
|
301031
|
+
const ipfsDir = join81(ctx3.repoRoot, ".oa", "ipfs");
|
|
301032
|
+
const ipfsLocalDir = join81(ipfsDir, "local");
|
|
300778
301033
|
let ipfsFiles = 0;
|
|
300779
301034
|
let ipfsBytes = 0;
|
|
300780
301035
|
let heliaBlocks = 0;
|
|
300781
301036
|
let heliaBytes = 0;
|
|
300782
301037
|
try {
|
|
300783
|
-
if (
|
|
301038
|
+
if (existsSync65(ipfsLocalDir)) {
|
|
300784
301039
|
const files = readdirSync17(ipfsLocalDir).filter((f2) => f2.endsWith(".json"));
|
|
300785
301040
|
ipfsFiles = files.length;
|
|
300786
301041
|
for (const f2 of files) {
|
|
300787
301042
|
try {
|
|
300788
|
-
ipfsBytes += statSync19(
|
|
301043
|
+
ipfsBytes += statSync19(join81(ipfsLocalDir, f2)).size;
|
|
300789
301044
|
} catch {
|
|
300790
301045
|
}
|
|
300791
301046
|
}
|
|
300792
301047
|
}
|
|
300793
|
-
const heliaBlockDir =
|
|
300794
|
-
if (
|
|
301048
|
+
const heliaBlockDir = join81(ipfsDir, "blocks");
|
|
301049
|
+
if (existsSync65(heliaBlockDir)) {
|
|
300795
301050
|
const walkDir = (dir) => {
|
|
300796
301051
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300797
|
-
if (entry.isDirectory()) walkDir(
|
|
301052
|
+
if (entry.isDirectory()) walkDir(join81(dir, entry.name));
|
|
300798
301053
|
else {
|
|
300799
301054
|
heliaBlocks++;
|
|
300800
301055
|
try {
|
|
300801
|
-
heliaBytes += statSync19(
|
|
301056
|
+
heliaBytes += statSync19(join81(dir, entry.name)).size;
|
|
300802
301057
|
} catch {
|
|
300803
301058
|
}
|
|
300804
301059
|
}
|
|
@@ -300814,9 +301069,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300814
301069
|
lines.push(` Blocks: ${c3.bold(String(heliaBlocks))} Size: ${c3.bold(formatFileSize(heliaBytes))}`);
|
|
300815
301070
|
lines.push(` Backend: ${heliaBlocks > 0 ? c3.green("helia-ipfs") : c3.yellow("sha256-local (Helia not initialized)")}`);
|
|
300816
301071
|
try {
|
|
300817
|
-
const statusFile =
|
|
300818
|
-
if (
|
|
300819
|
-
const status = JSON.parse(
|
|
301072
|
+
const statusFile = join81(ctx3.repoRoot, ".oa", "nexus", "status.json");
|
|
301073
|
+
if (existsSync65(statusFile)) {
|
|
301074
|
+
const status = JSON.parse(readFileSync50(statusFile, "utf8"));
|
|
300820
301075
|
if (status.peerId) {
|
|
300821
301076
|
lines.push(`
|
|
300822
301077
|
${c3.bold("Peer Info")}`);
|
|
@@ -300835,11 +301090,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300835
301090
|
${c3.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
|
|
300836
301091
|
lines.push(`
|
|
300837
301092
|
${c3.bold("Identity Kernel")}`);
|
|
300838
|
-
const idDir =
|
|
301093
|
+
const idDir = join81(ctx3.repoRoot, ".oa", "identity");
|
|
300839
301094
|
try {
|
|
300840
|
-
const stateFile =
|
|
300841
|
-
if (
|
|
300842
|
-
const state = JSON.parse(
|
|
301095
|
+
const stateFile = join81(idDir, "self-state.json");
|
|
301096
|
+
if (existsSync65(stateFile)) {
|
|
301097
|
+
const state = JSON.parse(readFileSync50(stateFile, "utf8"));
|
|
300843
301098
|
lines.push(` Version: ${c3.bold("v" + (state.version ?? "?"))} Sessions: ${c3.bold(String(state.session_count ?? 0))}`);
|
|
300844
301099
|
if (state.narrative_summary) {
|
|
300845
301100
|
lines.push(` Narrative: ${c3.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
|
|
@@ -300848,9 +301103,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300848
301103
|
const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
|
|
300849
301104
|
lines.push(` Traits: ${c3.dim(traits.slice(0, 60))}`);
|
|
300850
301105
|
}
|
|
300851
|
-
const cidFile =
|
|
300852
|
-
if (
|
|
300853
|
-
const cids = JSON.parse(
|
|
301106
|
+
const cidFile = join81(idDir, "cids.json");
|
|
301107
|
+
if (existsSync65(cidFile)) {
|
|
301108
|
+
const cids = JSON.parse(readFileSync50(cidFile, "utf8"));
|
|
300854
301109
|
const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
|
|
300855
301110
|
if (lastCid) lines.push(` Last CID: ${c3.dim(String(lastCid).slice(0, 50))}`);
|
|
300856
301111
|
}
|
|
@@ -300862,9 +301117,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300862
301117
|
lines.push(`
|
|
300863
301118
|
${c3.bold("Memory Sentiment")}`);
|
|
300864
301119
|
try {
|
|
300865
|
-
const metaFile =
|
|
300866
|
-
if (
|
|
300867
|
-
const store2 = JSON.parse(
|
|
301120
|
+
const metaFile = join81(ctx3.repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
301121
|
+
if (existsSync65(metaFile)) {
|
|
301122
|
+
const store2 = JSON.parse(readFileSync50(metaFile, "utf8"));
|
|
300868
301123
|
const active = store2.filter((m2) => m2.type !== "quarantine");
|
|
300869
301124
|
const recoveries = active.filter((m2) => m2.content?.startsWith("[recovery]")).length;
|
|
300870
301125
|
const strategies = active.filter((m2) => m2.content?.startsWith("[strategy]")).length;
|
|
@@ -300882,8 +301137,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300882
301137
|
} catch {
|
|
300883
301138
|
}
|
|
300884
301139
|
try {
|
|
300885
|
-
const dbPath =
|
|
300886
|
-
if (
|
|
301140
|
+
const dbPath = join81(ctx3.repoRoot, ".oa", "memory", "structured.db");
|
|
301141
|
+
if (existsSync65(dbPath)) {
|
|
300887
301142
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
300888
301143
|
const db = initDb2(dbPath);
|
|
300889
301144
|
const memStore = new ProceduralMemoryStore2(db);
|
|
@@ -300904,8 +301159,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300904
301159
|
lines.push(`
|
|
300905
301160
|
${c3.bold("Storage Overview")}
|
|
300906
301161
|
`);
|
|
300907
|
-
const oaDir =
|
|
300908
|
-
if (!
|
|
301162
|
+
const oaDir = join81(ctx3.repoRoot, ".oa");
|
|
301163
|
+
if (!existsSync65(oaDir)) {
|
|
300909
301164
|
lines.push(` ${c3.dim("No .oa/ directory found.")}`);
|
|
300910
301165
|
safeLog(lines.join("\n") + "\n");
|
|
300911
301166
|
return "handled";
|
|
@@ -300915,7 +301170,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300915
301170
|
const walkStorage = (dir, category) => {
|
|
300916
301171
|
try {
|
|
300917
301172
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300918
|
-
const full =
|
|
301173
|
+
const full = join81(dir, entry.name);
|
|
300919
301174
|
if (entry.isDirectory()) {
|
|
300920
301175
|
const subCat = category || entry.name;
|
|
300921
301176
|
walkStorage(full, subCat);
|
|
@@ -300950,9 +301205,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300950
301205
|
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
300951
301206
|
const name10 = entry.name.toLowerCase();
|
|
300952
301207
|
if (sensitivePatterns.some((p2) => name10.includes(p2))) {
|
|
300953
|
-
sensitiveFound.push(
|
|
301208
|
+
sensitiveFound.push(join81(dir, entry.name).replace(oaDir + "/", ""));
|
|
300954
301209
|
}
|
|
300955
|
-
if (entry.isDirectory()) checkSensitive(
|
|
301210
|
+
if (entry.isDirectory()) checkSensitive(join81(dir, entry.name));
|
|
300956
301211
|
}
|
|
300957
301212
|
} catch {
|
|
300958
301213
|
}
|
|
@@ -300980,8 +301235,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300980
301235
|
renderInfo("Supported: .wav .mp3 .flac .ogg (audio→transcribe) | .pdf .txt .md (text→chunk)");
|
|
300981
301236
|
return "handled";
|
|
300982
301237
|
}
|
|
300983
|
-
const resolvedPath =
|
|
300984
|
-
if (!
|
|
301238
|
+
const resolvedPath = join81(ctx3.repoRoot, filePath);
|
|
301239
|
+
if (!existsSync65(resolvedPath)) {
|
|
300985
301240
|
renderWarning(`File not found: ${resolvedPath}`);
|
|
300986
301241
|
return "handled";
|
|
300987
301242
|
}
|
|
@@ -300997,9 +301252,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
300997
301252
|
}
|
|
300998
301253
|
try {
|
|
300999
301254
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
301000
|
-
const dbDir =
|
|
301255
|
+
const dbDir = join81(ctx3.repoRoot, ".oa", "memory");
|
|
301001
301256
|
mkdirSync37(dbDir, { recursive: true });
|
|
301002
|
-
const db = initDb2(
|
|
301257
|
+
const db = initDb2(join81(dbDir, "structured.db"));
|
|
301003
301258
|
const memStore = new ProceduralMemoryStore2(db);
|
|
301004
301259
|
if (isAudio) {
|
|
301005
301260
|
renderInfo(`Transcribing: ${filePath}...`);
|
|
@@ -301043,7 +301298,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301043
301298
|
return "handled";
|
|
301044
301299
|
}
|
|
301045
301300
|
} else {
|
|
301046
|
-
content =
|
|
301301
|
+
content = readFileSync50(resolvedPath, "utf8");
|
|
301047
301302
|
}
|
|
301048
301303
|
if (!content.trim()) {
|
|
301049
301304
|
renderWarning("No content extracted.");
|
|
@@ -301081,9 +301336,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301081
301336
|
}
|
|
301082
301337
|
case "fortemi": {
|
|
301083
301338
|
const fortemiSubCmd = (arg || "").trim().toLowerCase();
|
|
301084
|
-
const fortemiDir =
|
|
301085
|
-
const altFortemiDir =
|
|
301086
|
-
const fDir =
|
|
301339
|
+
const fortemiDir = join81(ctx3.repoRoot, "..", "fortemi-react");
|
|
301340
|
+
const altFortemiDir = join81(nodeOs.homedir(), "fortemi-react");
|
|
301341
|
+
const fDir = existsSync65(fortemiDir) ? fortemiDir : existsSync65(altFortemiDir) ? altFortemiDir : null;
|
|
301087
301342
|
if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
|
|
301088
301343
|
if (!fDir) {
|
|
301089
301344
|
renderWarning("fortemi-react not found adjacent or in home directory.");
|
|
@@ -301098,14 +301353,14 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301098
301353
|
// 24h
|
|
301099
301354
|
nonce: Math.random().toString(36).slice(2, 10)
|
|
301100
301355
|
};
|
|
301101
|
-
const jwtFile =
|
|
301102
|
-
mkdirSync37(
|
|
301356
|
+
const jwtFile = join81(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
|
|
301357
|
+
mkdirSync37(join81(ctx3.repoRoot, ".oa"), { recursive: true });
|
|
301103
301358
|
writeFileSync34(jwtFile, JSON.stringify(jwtPayload, null, 2));
|
|
301104
301359
|
renderInfo(`Launching fortemi-react from ${fDir}...`);
|
|
301105
301360
|
try {
|
|
301106
301361
|
const { spawn: spawn27 } = __require("node:child_process");
|
|
301107
301362
|
const child = spawn27("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
|
|
301108
|
-
cwd:
|
|
301363
|
+
cwd: join81(fDir, "apps", "standalone"),
|
|
301109
301364
|
stdio: "ignore",
|
|
301110
301365
|
detached: true,
|
|
301111
301366
|
env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
|
|
@@ -301114,7 +301369,7 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301114
301369
|
renderInfo("Fortemi-React starting on http://localhost:3000");
|
|
301115
301370
|
renderInfo(`JWT saved to ${jwtFile}`);
|
|
301116
301371
|
renderInfo("Memory operations will proxy to fortemi when available.");
|
|
301117
|
-
const bridgeFile =
|
|
301372
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301118
301373
|
writeFileSync34(bridgeFile, JSON.stringify({
|
|
301119
301374
|
url: "http://localhost:3000",
|
|
301120
301375
|
pid: child.pid,
|
|
@@ -301127,12 +301382,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301127
301382
|
return "handled";
|
|
301128
301383
|
}
|
|
301129
301384
|
if (fortemiSubCmd === "status") {
|
|
301130
|
-
const bridgeFile =
|
|
301131
|
-
if (!
|
|
301385
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301386
|
+
if (!existsSync65(bridgeFile)) {
|
|
301132
301387
|
renderInfo("Fortemi bridge: not connected. Run /fortemi start");
|
|
301133
301388
|
return "handled";
|
|
301134
301389
|
}
|
|
301135
|
-
const bridge = JSON.parse(
|
|
301390
|
+
const bridge = JSON.parse(readFileSync50(bridgeFile, "utf8"));
|
|
301136
301391
|
let alive = false;
|
|
301137
301392
|
try {
|
|
301138
301393
|
process.kill(bridge.pid, 0);
|
|
@@ -301152,15 +301407,15 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
301152
301407
|
lines.push(` Process: ${alive ? c3.green("running") : c3.yellow("not running")} (PID ${bridge.pid})`);
|
|
301153
301408
|
lines.push(` HTTP: ${httpOk ? c3.green("connected") : c3.yellow("unreachable")}`);
|
|
301154
301409
|
lines.push(` Started: ${bridge.startedAt}`);
|
|
301155
|
-
lines.push(` JWT: ${
|
|
301410
|
+
lines.push(` JWT: ${existsSync65(bridge.jwtFile) ? c3.green("valid") : c3.yellow("missing")}`);
|
|
301156
301411
|
lines.push("");
|
|
301157
301412
|
safeLog(lines.join("\n"));
|
|
301158
301413
|
return "handled";
|
|
301159
301414
|
}
|
|
301160
301415
|
if (fortemiSubCmd === "stop") {
|
|
301161
|
-
const bridgeFile =
|
|
301162
|
-
if (
|
|
301163
|
-
const bridge = JSON.parse(
|
|
301416
|
+
const bridgeFile = join81(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
|
|
301417
|
+
if (existsSync65(bridgeFile)) {
|
|
301418
|
+
const bridge = JSON.parse(readFileSync50(bridgeFile, "utf8"));
|
|
301164
301419
|
try {
|
|
301165
301420
|
process.kill(bridge.pid, "SIGTERM");
|
|
301166
301421
|
} catch {
|
|
@@ -301612,11 +301867,24 @@ Clone a new voice: /voice clone <wav-file> [name]`);
|
|
|
301612
301867
|
case "neovim":
|
|
301613
301868
|
case "nvim":
|
|
301614
301869
|
case "vim": {
|
|
301870
|
+
const tasksRenderer = await Promise.resolve().then(() => (init_tui_tasks_renderer(), tui_tasks_renderer_exports)).catch(() => null);
|
|
301615
301871
|
if (isNeovimActive()) {
|
|
301616
301872
|
await stopNeovimMode();
|
|
301617
301873
|
ctx3.clearScreen();
|
|
301618
301874
|
renderInfo("Neovim mode stopped. Main waterfall restored.");
|
|
301875
|
+
try {
|
|
301876
|
+
tasksRenderer?.setTuiTasksScope({ neovimActive: false });
|
|
301877
|
+
} catch {
|
|
301878
|
+
}
|
|
301879
|
+
try {
|
|
301880
|
+
tasksRenderer?.refreshTuiTasks();
|
|
301881
|
+
} catch {
|
|
301882
|
+
}
|
|
301619
301883
|
} else {
|
|
301884
|
+
try {
|
|
301885
|
+
tasksRenderer?.setTuiTasksScope({ neovimActive: true });
|
|
301886
|
+
} catch {
|
|
301887
|
+
}
|
|
301620
301888
|
ctx3.retireCarousel?.();
|
|
301621
301889
|
const L = layout();
|
|
301622
301890
|
const contentRows = ctx3.availableContentRows?.() ?? Math.max(5, L.contentHeight);
|
|
@@ -301970,9 +302238,9 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
301970
302238
|
}
|
|
301971
302239
|
}
|
|
301972
302240
|
}
|
|
301973
|
-
const _spLogDir =
|
|
302241
|
+
const _spLogDir = join81(projectDir, ".oa", "sponsor");
|
|
301974
302242
|
mkdirSync37(_spLogDir, { recursive: true });
|
|
301975
|
-
const _spLogFile =
|
|
302243
|
+
const _spLogFile = join81(_spLogDir, "sponsor-startup.log");
|
|
301976
302244
|
const _spLog = (msg) => {
|
|
301977
302245
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
301978
302246
|
`;
|
|
@@ -302082,17 +302350,17 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302082
302350
|
}
|
|
302083
302351
|
if (!sponsorUrl && !sponsorPeerId) {
|
|
302084
302352
|
_spLog("FAILED — no tunnelUrl and no peerId");
|
|
302085
|
-
_spLog(`nexusDir checked: ${
|
|
302086
|
-
_spLog(`status.json exists: ${
|
|
302087
|
-
_spLog(`daemon.pid exists: ${
|
|
302353
|
+
_spLog(`nexusDir checked: ${join81(projectDir, ".oa", "nexus")}`);
|
|
302354
|
+
_spLog(`status.json exists: ${existsSync65(join81(projectDir, ".oa", "nexus", "status.json"))}`);
|
|
302355
|
+
_spLog(`daemon.pid exists: ${existsSync65(join81(projectDir, ".oa", "nexus", "daemon.pid"))}`);
|
|
302088
302356
|
try {
|
|
302089
|
-
const _statusRaw =
|
|
302357
|
+
const _statusRaw = readFileSync50(join81(projectDir, ".oa", "nexus", "status.json"), "utf8");
|
|
302090
302358
|
_spLog(`status.json content: ${_statusRaw.slice(0, 300)}`);
|
|
302091
302359
|
} catch (e2) {
|
|
302092
302360
|
_spLog(`status.json read error: ${e2}`);
|
|
302093
302361
|
}
|
|
302094
302362
|
try {
|
|
302095
|
-
const _errRaw =
|
|
302363
|
+
const _errRaw = readFileSync50(join81(projectDir, ".oa", "nexus", "daemon.err"), "utf8");
|
|
302096
302364
|
_spLog(`daemon.err (last 500): ${_errRaw.slice(-500)}`);
|
|
302097
302365
|
} catch (e2) {
|
|
302098
302366
|
_spLog(`daemon.err read error: ${e2}`);
|
|
@@ -302111,7 +302379,7 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302111
302379
|
try {
|
|
302112
302380
|
const { homedir: homedir39 } = __require("os");
|
|
302113
302381
|
const namePath = __require("path").join(homedir39(), ".open-agents", "agent-name");
|
|
302114
|
-
if (
|
|
302382
|
+
if (existsSync65(namePath)) sponsorName = readFileSync50(namePath, "utf8").trim();
|
|
302115
302383
|
} catch {
|
|
302116
302384
|
}
|
|
302117
302385
|
if (!sponsorName) sponsorName = "OA Sponsor";
|
|
@@ -302186,9 +302454,9 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
|
|
|
302186
302454
|
if (result) {
|
|
302187
302455
|
renderInfo("Sponsor wizard completed.");
|
|
302188
302456
|
try {
|
|
302189
|
-
const nexusPidFile =
|
|
302190
|
-
if (
|
|
302191
|
-
const nPid = parseInt(
|
|
302457
|
+
const nexusPidFile = join81(projectDir, ".oa", "nexus", "daemon.pid");
|
|
302458
|
+
if (existsSync65(nexusPidFile)) {
|
|
302459
|
+
const nPid = parseInt(readFileSync50(nexusPidFile, "utf8").trim(), 10);
|
|
302192
302460
|
if (nPid > 0) {
|
|
302193
302461
|
registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
|
|
302194
302462
|
}
|
|
@@ -303252,13 +303520,13 @@ async function showCohereDashboard(ctx3) {
|
|
|
303252
303520
|
} else if (idResult.key === "view") {
|
|
303253
303521
|
await ik.execute({ operation: "hydrate" });
|
|
303254
303522
|
} else if (idResult.key === "history") {
|
|
303255
|
-
const snapDir =
|
|
303256
|
-
if (
|
|
303523
|
+
const snapDir = join81(ctx3.repoRoot, ".oa", "identity", "snapshots");
|
|
303524
|
+
if (existsSync65(snapDir)) {
|
|
303257
303525
|
const snaps = readdirSync17(snapDir).filter((f2) => f2.endsWith(".json")).sort().reverse();
|
|
303258
303526
|
const snapItems = snaps.slice(0, 20).map((f2) => ({
|
|
303259
303527
|
key: f2,
|
|
303260
303528
|
label: f2.replace(".json", ""),
|
|
303261
|
-
detail: `${formatFileSize(statSync19(
|
|
303529
|
+
detail: `${formatFileSize(statSync19(join81(snapDir, f2)).size)}`
|
|
303262
303530
|
}));
|
|
303263
303531
|
if (snapItems.length > 0) {
|
|
303264
303532
|
await tuiSelect({
|
|
@@ -304261,11 +304529,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
|
|
|
304261
304529
|
}
|
|
304262
304530
|
} catch {
|
|
304263
304531
|
}
|
|
304264
|
-
const sponsorDir2 =
|
|
304265
|
-
const knownFile =
|
|
304532
|
+
const sponsorDir2 = join81(ctx3.repoRoot ?? process.cwd(), ".oa", "sponsor");
|
|
304533
|
+
const knownFile = join81(sponsorDir2, "known-sponsors.json");
|
|
304266
304534
|
try {
|
|
304267
|
-
if (
|
|
304268
|
-
const saved = JSON.parse(
|
|
304535
|
+
if (existsSync65(knownFile)) {
|
|
304536
|
+
const saved = JSON.parse(readFileSync50(knownFile, "utf8"));
|
|
304269
304537
|
for (const s2 of saved) {
|
|
304270
304538
|
if (!sponsors.some((sp) => sp.url === s2.url)) {
|
|
304271
304539
|
sponsors.push({ ...s2, source: "saved" });
|
|
@@ -304416,7 +304684,7 @@ async function handleSponsoredEndpoint(ctx3, local) {
|
|
|
304416
304684
|
const saveKey = selected.url || selected.peerId || selected.name;
|
|
304417
304685
|
try {
|
|
304418
304686
|
mkdirSync37(sponsorDir2, { recursive: true });
|
|
304419
|
-
const existing =
|
|
304687
|
+
const existing = existsSync65(knownFile) ? JSON.parse(readFileSync50(knownFile, "utf8")) : [];
|
|
304420
304688
|
const updated = existing.filter((s2) => (s2.url || s2.peerId || s2.name) !== saveKey);
|
|
304421
304689
|
updated.push(selected);
|
|
304422
304690
|
writeFileSync34(knownFile, JSON.stringify(updated, null, 2), "utf8");
|
|
@@ -306161,10 +306429,10 @@ var init_commands = __esm({
|
|
|
306161
306429
|
});
|
|
306162
306430
|
|
|
306163
306431
|
// packages/cli/src/tui/project-context.ts
|
|
306164
|
-
import { existsSync as
|
|
306165
|
-
import { join as
|
|
306432
|
+
import { existsSync as existsSync66, readFileSync as readFileSync51, readdirSync as readdirSync18 } from "node:fs";
|
|
306433
|
+
import { join as join82, basename as basename13 } from "node:path";
|
|
306166
306434
|
import { execSync as execSync51 } from "node:child_process";
|
|
306167
|
-
import { homedir as
|
|
306435
|
+
import { homedir as homedir30, platform as platform5, release } from "node:os";
|
|
306168
306436
|
function getModelTier(modelName) {
|
|
306169
306437
|
const m2 = modelName.toLowerCase();
|
|
306170
306438
|
const sizeMatch = m2.match(/\b(\d+)b\b/);
|
|
@@ -306193,10 +306461,10 @@ function loadProjectMap(repoRoot) {
|
|
|
306193
306461
|
if (!hasOaDirectory(repoRoot)) {
|
|
306194
306462
|
initOaDirectory(repoRoot);
|
|
306195
306463
|
}
|
|
306196
|
-
const mapPath2 =
|
|
306197
|
-
if (
|
|
306464
|
+
const mapPath2 = join82(repoRoot, OA_DIR, "context", "project-map.md");
|
|
306465
|
+
if (existsSync66(mapPath2)) {
|
|
306198
306466
|
try {
|
|
306199
|
-
const content =
|
|
306467
|
+
const content = readFileSync51(mapPath2, "utf-8");
|
|
306200
306468
|
return content;
|
|
306201
306469
|
} catch {
|
|
306202
306470
|
}
|
|
@@ -306235,27 +306503,27 @@ ${log22}`);
|
|
|
306235
306503
|
}
|
|
306236
306504
|
function loadMemoryContext(repoRoot) {
|
|
306237
306505
|
const sections = [];
|
|
306238
|
-
const oaMemDir =
|
|
306506
|
+
const oaMemDir = join82(repoRoot, OA_DIR, "memory");
|
|
306239
306507
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
306240
306508
|
if (oaEntries) sections.push(oaEntries);
|
|
306241
|
-
const legacyMemDir =
|
|
306242
|
-
if (legacyMemDir !== oaMemDir &&
|
|
306509
|
+
const legacyMemDir = join82(repoRoot, ".open-agents", "memory");
|
|
306510
|
+
if (legacyMemDir !== oaMemDir && existsSync66(legacyMemDir)) {
|
|
306243
306511
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
306244
306512
|
if (legacyEntries) sections.push(legacyEntries);
|
|
306245
306513
|
}
|
|
306246
|
-
const globalMemDir =
|
|
306514
|
+
const globalMemDir = join82(homedir30(), ".open-agents", "memory");
|
|
306247
306515
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
306248
306516
|
if (globalEntries) sections.push(globalEntries);
|
|
306249
306517
|
return sections.join("\n\n");
|
|
306250
306518
|
}
|
|
306251
306519
|
function loadMemoryDir(memDir, scope) {
|
|
306252
|
-
if (!
|
|
306520
|
+
if (!existsSync66(memDir)) return "";
|
|
306253
306521
|
const lines = [];
|
|
306254
306522
|
try {
|
|
306255
306523
|
const files = readdirSync18(memDir).filter((f2) => f2.endsWith(".json"));
|
|
306256
306524
|
for (const file of files.slice(0, 10)) {
|
|
306257
306525
|
try {
|
|
306258
|
-
const raw =
|
|
306526
|
+
const raw = readFileSync51(join82(memDir, file), "utf-8");
|
|
306259
306527
|
const entries = JSON.parse(raw);
|
|
306260
306528
|
const topic = basename13(file, ".json");
|
|
306261
306529
|
const keys = Object.keys(entries);
|
|
@@ -306760,8 +307028,8 @@ __export(banner_exports, {
|
|
|
306760
307028
|
saveBannerDesign: () => saveBannerDesign,
|
|
306761
307029
|
setGridText: () => setGridText
|
|
306762
307030
|
});
|
|
306763
|
-
import { existsSync as
|
|
306764
|
-
import { join as
|
|
307031
|
+
import { existsSync as existsSync67, readFileSync as readFileSync52, writeFileSync as writeFileSync35, mkdirSync as mkdirSync38 } from "node:fs";
|
|
307032
|
+
import { join as join83 } from "node:path";
|
|
306765
307033
|
function generateMnemonic(seed) {
|
|
306766
307034
|
let h = 2166136261;
|
|
306767
307035
|
for (let i2 = 0; i2 < seed.length; i2++) {
|
|
@@ -306891,22 +307159,22 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
|
|
|
306891
307159
|
};
|
|
306892
307160
|
}
|
|
306893
307161
|
function saveBannerDesign(workDir, design) {
|
|
306894
|
-
const dir =
|
|
307162
|
+
const dir = join83(workDir, ".oa", "banners");
|
|
306895
307163
|
mkdirSync38(dir, { recursive: true });
|
|
306896
|
-
writeFileSync35(
|
|
307164
|
+
writeFileSync35(join83(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
|
|
306897
307165
|
}
|
|
306898
307166
|
function loadBannerDesign(workDir, id) {
|
|
306899
|
-
const file =
|
|
306900
|
-
if (!
|
|
307167
|
+
const file = join83(workDir, ".oa", "banners", `${id}.json`);
|
|
307168
|
+
if (!existsSync67(file)) return null;
|
|
306901
307169
|
try {
|
|
306902
|
-
return JSON.parse(
|
|
307170
|
+
return JSON.parse(readFileSync52(file, "utf8"));
|
|
306903
307171
|
} catch {
|
|
306904
307172
|
return null;
|
|
306905
307173
|
}
|
|
306906
307174
|
}
|
|
306907
307175
|
function listBannerDesigns(workDir) {
|
|
306908
|
-
const dir =
|
|
306909
|
-
if (!
|
|
307176
|
+
const dir = join83(workDir, ".oa", "banners");
|
|
307177
|
+
if (!existsSync67(dir)) return [];
|
|
306910
307178
|
try {
|
|
306911
307179
|
const { readdirSync: readdirSync31 } = __require("node:fs");
|
|
306912
307180
|
return readdirSync31(dir).filter((f2) => f2.endsWith(".json")).map((f2) => f2.replace(".json", ""));
|
|
@@ -307213,21 +307481,21 @@ var init_banner = __esm({
|
|
|
307213
307481
|
});
|
|
307214
307482
|
|
|
307215
307483
|
// packages/cli/src/tui/carousel-descriptors.ts
|
|
307216
|
-
import { existsSync as
|
|
307217
|
-
import { join as
|
|
307484
|
+
import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync36, mkdirSync as mkdirSync39, readdirSync as readdirSync19 } from "node:fs";
|
|
307485
|
+
import { join as join84, basename as basename14 } from "node:path";
|
|
307218
307486
|
function loadToolProfile(repoRoot) {
|
|
307219
|
-
const filePath =
|
|
307487
|
+
const filePath = join84(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
307220
307488
|
try {
|
|
307221
|
-
if (!
|
|
307222
|
-
return JSON.parse(
|
|
307489
|
+
if (!existsSync68(filePath)) return null;
|
|
307490
|
+
return JSON.parse(readFileSync53(filePath, "utf-8"));
|
|
307223
307491
|
} catch {
|
|
307224
307492
|
return null;
|
|
307225
307493
|
}
|
|
307226
307494
|
}
|
|
307227
307495
|
function saveToolProfile(repoRoot, profile) {
|
|
307228
|
-
const contextDir =
|
|
307496
|
+
const contextDir = join84(repoRoot, OA_DIR, "context");
|
|
307229
307497
|
mkdirSync39(contextDir, { recursive: true });
|
|
307230
|
-
writeFileSync36(
|
|
307498
|
+
writeFileSync36(join84(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
307231
307499
|
}
|
|
307232
307500
|
function categorizeToolCall(toolName) {
|
|
307233
307501
|
for (const cat2 of TOOL_CATEGORIES) {
|
|
@@ -307282,24 +307550,24 @@ function weightedColor(profile) {
|
|
|
307282
307550
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
307283
307551
|
}
|
|
307284
307552
|
function loadCachedDescriptors(repoRoot) {
|
|
307285
|
-
const filePath =
|
|
307553
|
+
const filePath = join84(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
307286
307554
|
try {
|
|
307287
|
-
if (!
|
|
307288
|
-
const cached = JSON.parse(
|
|
307555
|
+
if (!existsSync68(filePath)) return null;
|
|
307556
|
+
const cached = JSON.parse(readFileSync53(filePath, "utf-8"));
|
|
307289
307557
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
307290
307558
|
} catch {
|
|
307291
307559
|
return null;
|
|
307292
307560
|
}
|
|
307293
307561
|
}
|
|
307294
307562
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
307295
|
-
const contextDir =
|
|
307563
|
+
const contextDir = join84(repoRoot, OA_DIR, "context");
|
|
307296
307564
|
mkdirSync39(contextDir, { recursive: true });
|
|
307297
307565
|
const cached = {
|
|
307298
307566
|
phrases,
|
|
307299
307567
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
307300
307568
|
sourceHash
|
|
307301
307569
|
};
|
|
307302
|
-
writeFileSync36(
|
|
307570
|
+
writeFileSync36(join84(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
307303
307571
|
}
|
|
307304
307572
|
function generateDescriptors(repoRoot) {
|
|
307305
307573
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -307346,10 +307614,10 @@ function generateDescriptors(repoRoot) {
|
|
|
307346
307614
|
return phrases;
|
|
307347
307615
|
}
|
|
307348
307616
|
function extractFromPackageJson(repoRoot, tags) {
|
|
307349
|
-
const pkgPath =
|
|
307617
|
+
const pkgPath = join84(repoRoot, "package.json");
|
|
307350
307618
|
try {
|
|
307351
|
-
if (!
|
|
307352
|
-
const pkg = JSON.parse(
|
|
307619
|
+
if (!existsSync68(pkgPath)) return;
|
|
307620
|
+
const pkg = JSON.parse(readFileSync53(pkgPath, "utf-8"));
|
|
307353
307621
|
if (pkg.name && typeof pkg.name === "string") {
|
|
307354
307622
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
307355
307623
|
for (const p2 of parts) tags.push(p2);
|
|
@@ -307390,7 +307658,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
307390
307658
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
307391
307659
|
];
|
|
307392
307660
|
for (const check of manifestChecks) {
|
|
307393
|
-
if (
|
|
307661
|
+
if (existsSync68(join84(repoRoot, check.file))) {
|
|
307394
307662
|
tags.push(check.tag);
|
|
307395
307663
|
}
|
|
307396
307664
|
}
|
|
@@ -307412,15 +307680,15 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
307412
307680
|
}
|
|
307413
307681
|
}
|
|
307414
307682
|
function extractFromMemory(repoRoot, tags) {
|
|
307415
|
-
const memoryDir =
|
|
307683
|
+
const memoryDir = join84(repoRoot, OA_DIR, "memory");
|
|
307416
307684
|
try {
|
|
307417
|
-
if (!
|
|
307685
|
+
if (!existsSync68(memoryDir)) return;
|
|
307418
307686
|
const files = readdirSync19(memoryDir).filter((f2) => f2.endsWith(".json"));
|
|
307419
307687
|
for (const file of files) {
|
|
307420
307688
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
307421
307689
|
tags.push(topic);
|
|
307422
307690
|
try {
|
|
307423
|
-
const data = JSON.parse(
|
|
307691
|
+
const data = JSON.parse(readFileSync53(join84(memoryDir, file), "utf-8"));
|
|
307424
307692
|
if (data && typeof data === "object") {
|
|
307425
307693
|
const keys = Object.keys(data).slice(0, 3);
|
|
307426
307694
|
for (const key of keys) {
|
|
@@ -308115,10 +308383,10 @@ var init_stream_renderer = __esm({
|
|
|
308115
308383
|
|
|
308116
308384
|
// packages/cli/src/tui/edit-history.ts
|
|
308117
308385
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync40 } from "node:fs";
|
|
308118
|
-
import { join as
|
|
308386
|
+
import { join as join85 } from "node:path";
|
|
308119
308387
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
308120
|
-
const historyDir =
|
|
308121
|
-
const logPath2 =
|
|
308388
|
+
const historyDir = join85(repoRoot, ".oa", "history");
|
|
308389
|
+
const logPath2 = join85(historyDir, "edits.jsonl");
|
|
308122
308390
|
try {
|
|
308123
308391
|
mkdirSync40(historyDir, { recursive: true });
|
|
308124
308392
|
} catch {
|
|
@@ -308228,17 +308496,17 @@ var init_edit_history = __esm({
|
|
|
308228
308496
|
});
|
|
308229
308497
|
|
|
308230
308498
|
// packages/cli/src/tui/promptLoader.ts
|
|
308231
|
-
import { readFileSync as
|
|
308232
|
-
import { join as
|
|
308499
|
+
import { readFileSync as readFileSync54, existsSync as existsSync69 } from "node:fs";
|
|
308500
|
+
import { join as join86, dirname as dirname24 } from "node:path";
|
|
308233
308501
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
308234
308502
|
function loadPrompt3(promptPath, vars) {
|
|
308235
308503
|
let content = cache6.get(promptPath);
|
|
308236
308504
|
if (content === void 0) {
|
|
308237
|
-
const fullPath =
|
|
308238
|
-
if (!
|
|
308505
|
+
const fullPath = join86(PROMPTS_DIR3, promptPath);
|
|
308506
|
+
if (!existsSync69(fullPath)) {
|
|
308239
308507
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
308240
308508
|
}
|
|
308241
|
-
content =
|
|
308509
|
+
content = readFileSync54(fullPath, "utf-8");
|
|
308242
308510
|
cache6.set(promptPath, content);
|
|
308243
308511
|
}
|
|
308244
308512
|
if (!vars) return content;
|
|
@@ -308250,16 +308518,16 @@ var init_promptLoader3 = __esm({
|
|
|
308250
308518
|
"use strict";
|
|
308251
308519
|
__filename5 = fileURLToPath14(import.meta.url);
|
|
308252
308520
|
__dirname7 = dirname24(__filename5);
|
|
308253
|
-
devPath2 =
|
|
308254
|
-
publishedPath2 =
|
|
308255
|
-
PROMPTS_DIR3 =
|
|
308521
|
+
devPath2 = join86(__dirname7, "..", "..", "prompts");
|
|
308522
|
+
publishedPath2 = join86(__dirname7, "..", "prompts");
|
|
308523
|
+
PROMPTS_DIR3 = existsSync69(devPath2) ? devPath2 : publishedPath2;
|
|
308256
308524
|
cache6 = /* @__PURE__ */ new Map();
|
|
308257
308525
|
}
|
|
308258
308526
|
});
|
|
308259
308527
|
|
|
308260
308528
|
// packages/cli/src/tui/dream-engine.ts
|
|
308261
|
-
import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync37, readFileSync as
|
|
308262
|
-
import { join as
|
|
308529
|
+
import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync37, readFileSync as readFileSync55, existsSync as existsSync70, readdirSync as readdirSync20 } from "node:fs";
|
|
308530
|
+
import { join as join87, basename as basename15 } from "node:path";
|
|
308263
308531
|
import { execSync as execSync52 } from "node:child_process";
|
|
308264
308532
|
function setDreamWriteContent(fn) {
|
|
308265
308533
|
_dreamWriteContent = fn;
|
|
@@ -308272,10 +308540,10 @@ function dreamWrite(fn) {
|
|
|
308272
308540
|
}
|
|
308273
308541
|
}
|
|
308274
308542
|
function loadAutoresearchMemory(repoRoot) {
|
|
308275
|
-
const memoryPath =
|
|
308276
|
-
if (!
|
|
308543
|
+
const memoryPath = join87(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
308544
|
+
if (!existsSync70(memoryPath)) return "";
|
|
308277
308545
|
try {
|
|
308278
|
-
const raw =
|
|
308546
|
+
const raw = readFileSync55(memoryPath, "utf-8");
|
|
308279
308547
|
const data = JSON.parse(raw);
|
|
308280
308548
|
const sections = [];
|
|
308281
308549
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -308471,12 +308739,12 @@ var init_dream_engine = __esm({
|
|
|
308471
308739
|
const rawPath = String(args["path"] ?? "");
|
|
308472
308740
|
const content = String(args["content"] ?? "");
|
|
308473
308741
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
308474
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
308742
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join87(this.autoresearchDir, basename15(rawPath)) : join87(this.autoresearchDir, rawPath);
|
|
308475
308743
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
308476
308744
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
|
|
308477
308745
|
}
|
|
308478
308746
|
try {
|
|
308479
|
-
const dir =
|
|
308747
|
+
const dir = join87(targetPath, "..");
|
|
308480
308748
|
mkdirSync41(dir, { recursive: true });
|
|
308481
308749
|
writeFileSync37(targetPath, content, "utf-8");
|
|
308482
308750
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
|
|
@@ -308505,15 +308773,15 @@ var init_dream_engine = __esm({
|
|
|
308505
308773
|
const rawPath = String(args["path"] ?? "");
|
|
308506
308774
|
const oldStr = String(args["old_string"] ?? "");
|
|
308507
308775
|
const newStr = String(args["new_string"] ?? "");
|
|
308508
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
308776
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join87(this.autoresearchDir, basename15(rawPath)) : join87(this.autoresearchDir, rawPath);
|
|
308509
308777
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
308510
308778
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start2 };
|
|
308511
308779
|
}
|
|
308512
308780
|
try {
|
|
308513
|
-
if (!
|
|
308781
|
+
if (!existsSync70(targetPath)) {
|
|
308514
308782
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
|
|
308515
308783
|
}
|
|
308516
|
-
let content =
|
|
308784
|
+
let content = readFileSync55(targetPath, "utf-8");
|
|
308517
308785
|
if (!content.includes(oldStr)) {
|
|
308518
308786
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
|
|
308519
308787
|
}
|
|
@@ -308557,12 +308825,12 @@ var init_dream_engine = __esm({
|
|
|
308557
308825
|
const rawPath = String(args["path"] ?? "");
|
|
308558
308826
|
const content = String(args["content"] ?? "");
|
|
308559
308827
|
if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
|
|
308560
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
308828
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join87(this.dreamsDir, basename15(rawPath)) : join87(this.dreamsDir, rawPath);
|
|
308561
308829
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
308562
308830
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start2 };
|
|
308563
308831
|
}
|
|
308564
308832
|
try {
|
|
308565
|
-
const dir =
|
|
308833
|
+
const dir = join87(targetPath, "..");
|
|
308566
308834
|
mkdirSync41(dir, { recursive: true });
|
|
308567
308835
|
writeFileSync37(targetPath, content, "utf-8");
|
|
308568
308836
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
|
|
@@ -308591,15 +308859,15 @@ var init_dream_engine = __esm({
|
|
|
308591
308859
|
const rawPath = String(args["path"] ?? "");
|
|
308592
308860
|
const oldStr = String(args["old_string"] ?? "");
|
|
308593
308861
|
const newStr = String(args["new_string"] ?? "");
|
|
308594
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
308862
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join87(this.dreamsDir, basename15(rawPath)) : join87(this.dreamsDir, rawPath);
|
|
308595
308863
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
308596
308864
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start2 };
|
|
308597
308865
|
}
|
|
308598
308866
|
try {
|
|
308599
|
-
if (!
|
|
308867
|
+
if (!existsSync70(targetPath)) {
|
|
308600
308868
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start2 };
|
|
308601
308869
|
}
|
|
308602
|
-
let content =
|
|
308870
|
+
let content = readFileSync55(targetPath, "utf-8");
|
|
308603
308871
|
if (!content.includes(oldStr)) {
|
|
308604
308872
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
|
|
308605
308873
|
}
|
|
@@ -308652,7 +308920,7 @@ var init_dream_engine = __esm({
|
|
|
308652
308920
|
constructor(config, repoRoot) {
|
|
308653
308921
|
this.config = config;
|
|
308654
308922
|
this.repoRoot = repoRoot;
|
|
308655
|
-
this.dreamsDir =
|
|
308923
|
+
this.dreamsDir = join87(repoRoot, ".oa", "dreams");
|
|
308656
308924
|
this.state = {
|
|
308657
308925
|
mode: "default",
|
|
308658
308926
|
active: false,
|
|
@@ -308761,7 +309029,7 @@ ${result.summary}`;
|
|
|
308761
309029
|
if (mode !== "default" || cycle === totalCycles) {
|
|
308762
309030
|
renderDreamContraction(cycle);
|
|
308763
309031
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
308764
|
-
const summaryPath =
|
|
309032
|
+
const summaryPath = join87(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
308765
309033
|
writeFileSync37(summaryPath, cycleSummary, "utf-8");
|
|
308766
309034
|
}
|
|
308767
309035
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -309001,7 +309269,7 @@ After synthesis, call task_complete with the final prioritized summary.`,
|
|
|
309001
309269
|
}
|
|
309002
309270
|
/** Build role-specific tool sets for swarm agents */
|
|
309003
309271
|
buildSwarmTools(role, _workspace) {
|
|
309004
|
-
const autoresearchDir =
|
|
309272
|
+
const autoresearchDir = join87(this.repoRoot, ".oa", "autoresearch");
|
|
309005
309273
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
309006
309274
|
switch (role) {
|
|
309007
309275
|
case "researcher": {
|
|
@@ -309400,7 +309668,7 @@ Call task_complete with a human-readable summary of the autoresearch session.`,
|
|
|
309400
309668
|
workspace,
|
|
309401
309669
|
onEvent
|
|
309402
309670
|
);
|
|
309403
|
-
const reportPath =
|
|
309671
|
+
const reportPath = join87(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
309404
309672
|
const report = `# Autoresearch Swarm Report — Cycle ${cycleNum}
|
|
309405
309673
|
|
|
309406
309674
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -309489,7 +309757,7 @@ ${summaryResult}
|
|
|
309489
309757
|
}
|
|
309490
309758
|
/** Save workspace backup for lucid mode */
|
|
309491
309759
|
saveVersionCheckpoint(cycle) {
|
|
309492
|
-
const checkpointDir =
|
|
309760
|
+
const checkpointDir = join87(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
309493
309761
|
try {
|
|
309494
309762
|
mkdirSync41(checkpointDir, { recursive: true });
|
|
309495
309763
|
try {
|
|
@@ -309508,11 +309776,11 @@ ${summaryResult}
|
|
|
309508
309776
|
encoding: "utf-8",
|
|
309509
309777
|
timeout: 5e3
|
|
309510
309778
|
}).trim();
|
|
309511
|
-
writeFileSync37(
|
|
309512
|
-
writeFileSync37(
|
|
309513
|
-
writeFileSync37(
|
|
309779
|
+
writeFileSync37(join87(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
309780
|
+
writeFileSync37(join87(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
309781
|
+
writeFileSync37(join87(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
309514
309782
|
writeFileSync37(
|
|
309515
|
-
|
|
309783
|
+
join87(checkpointDir, "checkpoint.json"),
|
|
309516
309784
|
JSON.stringify({
|
|
309517
309785
|
cycle,
|
|
309518
309786
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -309524,7 +309792,7 @@ ${summaryResult}
|
|
|
309524
309792
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
309525
309793
|
} catch {
|
|
309526
309794
|
writeFileSync37(
|
|
309527
|
-
|
|
309795
|
+
join87(checkpointDir, "checkpoint.json"),
|
|
309528
309796
|
JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2),
|
|
309529
309797
|
"utf-8"
|
|
309530
309798
|
);
|
|
@@ -309585,7 +309853,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309585
309853
|
---
|
|
309586
309854
|
*Auto-generated by open-agents dream engine*
|
|
309587
309855
|
`;
|
|
309588
|
-
writeFileSync37(
|
|
309856
|
+
writeFileSync37(join87(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
309589
309857
|
} catch {
|
|
309590
309858
|
}
|
|
309591
309859
|
}
|
|
@@ -309606,7 +309874,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309606
309874
|
results: []
|
|
309607
309875
|
};
|
|
309608
309876
|
renderInfo("Memory consolidation starting — Phase 1: Orient → Phase 2: Gather → Phase 3: Consolidate → Phase 4: Prune");
|
|
309609
|
-
const memoryDir =
|
|
309877
|
+
const memoryDir = join87(this.repoRoot, ".oa", "memory");
|
|
309610
309878
|
mkdirSync41(memoryDir, { recursive: true });
|
|
309611
309879
|
let prompt;
|
|
309612
309880
|
try {
|
|
@@ -309672,7 +309940,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309672
309940
|
});
|
|
309673
309941
|
try {
|
|
309674
309942
|
writeFileSync37(
|
|
309675
|
-
|
|
309943
|
+
join87(memoryDir, ".last-consolidation"),
|
|
309676
309944
|
JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), summary: result.summary?.slice(0, 500) }) + "\n"
|
|
309677
309945
|
);
|
|
309678
309946
|
} catch {
|
|
@@ -309690,7 +309958,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
|
|
|
309690
309958
|
saveDreamState() {
|
|
309691
309959
|
try {
|
|
309692
309960
|
writeFileSync37(
|
|
309693
|
-
|
|
309961
|
+
join87(this.dreamsDir, "dream-state.json"),
|
|
309694
309962
|
JSON.stringify(this.state, null, 2) + "\n",
|
|
309695
309963
|
"utf-8"
|
|
309696
309964
|
);
|
|
@@ -310060,8 +310328,8 @@ var init_bless_engine = __esm({
|
|
|
310060
310328
|
});
|
|
310061
310329
|
|
|
310062
310330
|
// packages/cli/src/tui/dmn-engine.ts
|
|
310063
|
-
import { existsSync as
|
|
310064
|
-
import { join as
|
|
310331
|
+
import { existsSync as existsSync71, readFileSync as readFileSync56, writeFileSync as writeFileSync38, mkdirSync as mkdirSync42, readdirSync as readdirSync21, unlinkSync as unlinkSync18 } from "node:fs";
|
|
310332
|
+
import { join as join88, basename as basename16 } from "node:path";
|
|
310065
310333
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
310066
310334
|
const competenceReport = competence.length > 0 ? competence.map((c7) => {
|
|
310067
310335
|
const rate = c7.attempts > 0 ? Math.round(c7.successes / c7.attempts * 100) : 0;
|
|
@@ -310166,8 +310434,8 @@ var init_dmn_engine = __esm({
|
|
|
310166
310434
|
constructor(config, repoRoot) {
|
|
310167
310435
|
this.config = config;
|
|
310168
310436
|
this.repoRoot = repoRoot;
|
|
310169
|
-
this.stateDir =
|
|
310170
|
-
this.historyDir =
|
|
310437
|
+
this.stateDir = join88(repoRoot, ".oa", "dmn");
|
|
310438
|
+
this.historyDir = join88(repoRoot, ".oa", "dmn", "cycles");
|
|
310171
310439
|
mkdirSync42(this.historyDir, { recursive: true });
|
|
310172
310440
|
this.loadState();
|
|
310173
310441
|
}
|
|
@@ -310802,11 +311070,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310802
311070
|
async gatherMemoryTopics() {
|
|
310803
311071
|
const topics = [];
|
|
310804
311072
|
const dirs = [
|
|
310805
|
-
|
|
310806
|
-
|
|
311073
|
+
join88(this.repoRoot, ".oa", "memory"),
|
|
311074
|
+
join88(this.repoRoot, ".open-agents", "memory")
|
|
310807
311075
|
];
|
|
310808
311076
|
for (const dir of dirs) {
|
|
310809
|
-
if (!
|
|
311077
|
+
if (!existsSync71(dir)) continue;
|
|
310810
311078
|
try {
|
|
310811
311079
|
const files = readdirSync21(dir).filter((f2) => f2.endsWith(".json"));
|
|
310812
311080
|
for (const f2 of files) {
|
|
@@ -310820,10 +311088,10 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310820
311088
|
}
|
|
310821
311089
|
// ── State persistence ─────────────────────────────────────────────────
|
|
310822
311090
|
loadState() {
|
|
310823
|
-
const path5 =
|
|
310824
|
-
if (
|
|
311091
|
+
const path5 = join88(this.stateDir, "state.json");
|
|
311092
|
+
if (existsSync71(path5)) {
|
|
310825
311093
|
try {
|
|
310826
|
-
this.state = JSON.parse(
|
|
311094
|
+
this.state = JSON.parse(readFileSync56(path5, "utf-8"));
|
|
310827
311095
|
} catch {
|
|
310828
311096
|
}
|
|
310829
311097
|
}
|
|
@@ -310831,7 +311099,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310831
311099
|
saveState() {
|
|
310832
311100
|
try {
|
|
310833
311101
|
writeFileSync38(
|
|
310834
|
-
|
|
311102
|
+
join88(this.stateDir, "state.json"),
|
|
310835
311103
|
JSON.stringify(this.state, null, 2) + "\n",
|
|
310836
311104
|
"utf-8"
|
|
310837
311105
|
);
|
|
@@ -310842,7 +311110,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310842
311110
|
try {
|
|
310843
311111
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
310844
311112
|
writeFileSync38(
|
|
310845
|
-
|
|
311113
|
+
join88(this.historyDir, filename),
|
|
310846
311114
|
JSON.stringify(result, null, 2) + "\n",
|
|
310847
311115
|
"utf-8"
|
|
310848
311116
|
);
|
|
@@ -310850,7 +311118,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310850
311118
|
if (files.length > 50) {
|
|
310851
311119
|
for (const old of files.slice(0, files.length - 50)) {
|
|
310852
311120
|
try {
|
|
310853
|
-
unlinkSync18(
|
|
311121
|
+
unlinkSync18(join88(this.historyDir, old));
|
|
310854
311122
|
} catch {
|
|
310855
311123
|
}
|
|
310856
311124
|
}
|
|
@@ -310863,8 +311131,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
310863
311131
|
});
|
|
310864
311132
|
|
|
310865
311133
|
// packages/cli/src/tui/snr-engine.ts
|
|
310866
|
-
import { existsSync as
|
|
310867
|
-
import { join as
|
|
311134
|
+
import { existsSync as existsSync72, readdirSync as readdirSync22, readFileSync as readFileSync57 } from "node:fs";
|
|
311135
|
+
import { join as join89, basename as basename17 } from "node:path";
|
|
310868
311136
|
function computeDPrime(signalScores, noiseScores) {
|
|
310869
311137
|
if (signalScores.length === 0 || noiseScores.length === 0) return 0;
|
|
310870
311138
|
const mean = (arr) => arr.reduce((s2, v) => s2 + v, 0) / arr.length;
|
|
@@ -311148,18 +311416,18 @@ Call task_complete with the JSON array when done.`,
|
|
|
311148
311416
|
loadMemoryEntries(topics) {
|
|
311149
311417
|
const entries = [];
|
|
311150
311418
|
const dirs = [
|
|
311151
|
-
|
|
311152
|
-
|
|
311419
|
+
join89(this.repoRoot, ".oa", "memory"),
|
|
311420
|
+
join89(this.repoRoot, ".open-agents", "memory")
|
|
311153
311421
|
];
|
|
311154
311422
|
for (const dir of dirs) {
|
|
311155
|
-
if (!
|
|
311423
|
+
if (!existsSync72(dir)) continue;
|
|
311156
311424
|
try {
|
|
311157
311425
|
const files = readdirSync22(dir).filter((f2) => f2.endsWith(".json"));
|
|
311158
311426
|
for (const f2 of files) {
|
|
311159
311427
|
const topic = basename17(f2, ".json");
|
|
311160
311428
|
if (topics.length > 0 && !topics.includes(topic)) continue;
|
|
311161
311429
|
try {
|
|
311162
|
-
const data = JSON.parse(
|
|
311430
|
+
const data = JSON.parse(readFileSync57(join89(dir, f2), "utf-8"));
|
|
311163
311431
|
for (const [key, val] of Object.entries(data)) {
|
|
311164
311432
|
const value2 = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
311165
311433
|
entries.push({ topic, key, value: value2 });
|
|
@@ -311704,7 +311972,7 @@ var init_tool_policy = __esm({
|
|
|
311704
311972
|
|
|
311705
311973
|
// packages/cli/src/tui/telegram-bridge.ts
|
|
311706
311974
|
import { mkdirSync as mkdirSync43, unlinkSync as unlinkSync19 } from "node:fs";
|
|
311707
|
-
import { join as
|
|
311975
|
+
import { join as join90, resolve as resolve32 } from "node:path";
|
|
311708
311976
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
311709
311977
|
function convertMarkdownToTelegramHTML(md) {
|
|
311710
311978
|
let html = md;
|
|
@@ -312460,7 +312728,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
312460
312728
|
if (!res.ok) return null;
|
|
312461
312729
|
const buffer2 = Buffer.from(await res.arrayBuffer());
|
|
312462
312730
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension2}`;
|
|
312463
|
-
const localPath =
|
|
312731
|
+
const localPath = join90(this.mediaCacheDir, fileName);
|
|
312464
312732
|
await writeFileAsync(localPath, buffer2);
|
|
312465
312733
|
return localPath;
|
|
312466
312734
|
} catch {
|
|
@@ -312880,192 +313148,6 @@ var init_task_manager_singleton = __esm({
|
|
|
312880
313148
|
}
|
|
312881
313149
|
});
|
|
312882
313150
|
|
|
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
313151
|
// packages/cli/src/tui/mouse-filter.ts
|
|
313070
313152
|
var mouse_filter_exports = {};
|
|
313071
313153
|
__export(mouse_filter_exports, {
|
|
@@ -326503,8 +326585,18 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
|
|
|
326503
326585
|
banner.setFocused(focused);
|
|
326504
326586
|
banner.renderCurrentFrame();
|
|
326505
326587
|
});
|
|
326506
|
-
const { onOverlayLeave: onOverlayLeave2 } = await Promise.resolve().then(() => (init_overlay_lock(), overlay_lock_exports));
|
|
326588
|
+
const { onOverlayLeave: onOverlayLeave2, onOverlayEnter: onOverlayEnter2 } = await Promise.resolve().then(() => (init_overlay_lock(), overlay_lock_exports));
|
|
326589
|
+
onOverlayEnter2(() => {
|
|
326590
|
+
try {
|
|
326591
|
+
setTuiTasksScope({ overlayActive: true });
|
|
326592
|
+
} catch {
|
|
326593
|
+
}
|
|
326594
|
+
});
|
|
326507
326595
|
onOverlayLeave2(() => {
|
|
326596
|
+
try {
|
|
326597
|
+
setTuiTasksScope({ overlayActive: false });
|
|
326598
|
+
} catch {
|
|
326599
|
+
}
|
|
326508
326600
|
statusBar.suspendContentLayer();
|
|
326509
326601
|
banner.renderCurrentFrame();
|
|
326510
326602
|
statusBar.resumeContentLayer();
|
|
@@ -326513,6 +326605,10 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
|
|
|
326513
326605
|
if (statusBar.isActive) {
|
|
326514
326606
|
statusBar.refreshDisplay();
|
|
326515
326607
|
}
|
|
326608
|
+
try {
|
|
326609
|
+
refreshTuiTasks();
|
|
326610
|
+
} catch {
|
|
326611
|
+
}
|
|
326516
326612
|
});
|
|
326517
326613
|
if (cohereEnabled) {
|
|
326518
326614
|
statusBar.setCohereActive(true);
|