open-agents-ai 0.103.7 → 0.103.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +576 -156
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25086,6 +25086,13 @@ function renderSlashHelp() {
|
|
|
25086
25086
|
["/nexus", "Show nexus P2P network status (or connect/disconnect/rooms)"],
|
|
25087
25087
|
["/nexus connect", "Connect to the agent mesh network"],
|
|
25088
25088
|
["/nexus wallet", "Show wallet address and x402 payment status"],
|
|
25089
|
+
["/expose <backend>", "Share local inference via cloudflared tunnel"],
|
|
25090
|
+
["/expose <backend> --key", "Share with auto-generated auth key"],
|
|
25091
|
+
["/expose status", "Show gateway stats (requests, models, errors)"],
|
|
25092
|
+
["/expose stop", "Stop the expose gateway"],
|
|
25093
|
+
["/p2p start", "Join the P2P agent mesh network"],
|
|
25094
|
+
["/p2p status", "Show mesh peers and rooms"],
|
|
25095
|
+
["/p2p stop", "Leave the mesh network"],
|
|
25089
25096
|
["/style", "Show current response style"],
|
|
25090
25097
|
["/style <preset>", "Set style: concise, balanced, verbose, pedagogical"],
|
|
25091
25098
|
["/commands auto", "Allow agent to invoke slash commands as tools"],
|
|
@@ -25148,17 +25155,6 @@ function renderModelSwitch(oldModel, newModel) {
|
|
|
25148
25155
|
|
|
25149
25156
|
`);
|
|
25150
25157
|
}
|
|
25151
|
-
function renderConfig(config) {
|
|
25152
|
-
process.stdout.write(`
|
|
25153
|
-
${c2.bold("Configuration:")}
|
|
25154
|
-
|
|
25155
|
-
`);
|
|
25156
|
-
for (const [key, value] of Object.entries(config)) {
|
|
25157
|
-
process.stdout.write(` ${c2.cyan(key.padEnd(20))} ${value}
|
|
25158
|
-
`);
|
|
25159
|
-
}
|
|
25160
|
-
process.stdout.write("\n");
|
|
25161
|
-
}
|
|
25162
25158
|
function formatToolArgs(toolName, args, verbose) {
|
|
25163
25159
|
const maxArg = verbose ? 1e4 : Math.max(40, getTermWidth() - 20);
|
|
25164
25160
|
switch (toolName) {
|
|
@@ -26198,10 +26194,57 @@ var init_voice_session = __esm({
|
|
|
26198
26194
|
|
|
26199
26195
|
// packages/cli/dist/tui/expose.js
|
|
26200
26196
|
import { createServer as createServer2, request as httpRequest } from "node:http";
|
|
26201
|
-
import { spawn as spawn14 } from "node:child_process";
|
|
26197
|
+
import { spawn as spawn14, execSync as execSync25 } from "node:child_process";
|
|
26202
26198
|
import { EventEmitter as EventEmitter3 } from "node:events";
|
|
26203
26199
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
26204
26200
|
import { URL as URL2 } from "node:url";
|
|
26201
|
+
import { loadavg, cpus, totalmem, freemem } from "node:os";
|
|
26202
|
+
function collectSystemMetrics() {
|
|
26203
|
+
const [l1, l5, l15] = loadavg();
|
|
26204
|
+
const cores = cpus().length;
|
|
26205
|
+
const totalMem = totalmem();
|
|
26206
|
+
const freeMem = freemem();
|
|
26207
|
+
const usedMem = totalMem - freeMem;
|
|
26208
|
+
const gpu = {
|
|
26209
|
+
available: false,
|
|
26210
|
+
name: "",
|
|
26211
|
+
utilization: 0,
|
|
26212
|
+
vramUsedMB: 0,
|
|
26213
|
+
vramTotalMB: 0,
|
|
26214
|
+
vramUtilization: 0
|
|
26215
|
+
};
|
|
26216
|
+
try {
|
|
26217
|
+
const smi = execSync25("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
|
|
26218
|
+
const line = smi.trim().split("\n")[0];
|
|
26219
|
+
if (line) {
|
|
26220
|
+
const parts = line.split(",").map((s) => s.trim());
|
|
26221
|
+
gpu.available = true;
|
|
26222
|
+
gpu.utilization = parseInt(parts[0] ?? "0", 10) || 0;
|
|
26223
|
+
gpu.vramUsedMB = parseInt(parts[1] ?? "0", 10) || 0;
|
|
26224
|
+
gpu.vramTotalMB = parseInt(parts[2] ?? "0", 10) || 0;
|
|
26225
|
+
gpu.name = parts[3] ?? "";
|
|
26226
|
+
gpu.vramUtilization = gpu.vramTotalMB > 0 ? Math.round(gpu.vramUsedMB / gpu.vramTotalMB * 100) : 0;
|
|
26227
|
+
}
|
|
26228
|
+
} catch {
|
|
26229
|
+
}
|
|
26230
|
+
return {
|
|
26231
|
+
cpu: {
|
|
26232
|
+
loadAvg1m: Math.round(l1 * 100) / 100,
|
|
26233
|
+
loadAvg5m: Math.round(l5 * 100) / 100,
|
|
26234
|
+
loadAvg15m: Math.round(l15 * 100) / 100,
|
|
26235
|
+
cores,
|
|
26236
|
+
utilization: Math.min(100, Math.round(l1 / cores * 100))
|
|
26237
|
+
},
|
|
26238
|
+
memory: {
|
|
26239
|
+
totalGB: Math.round(totalMem / 1024 ** 3 * 10) / 10,
|
|
26240
|
+
freeGB: Math.round(freeMem / 1024 ** 3 * 10) / 10,
|
|
26241
|
+
usedGB: Math.round(usedMem / 1024 ** 3 * 10) / 10,
|
|
26242
|
+
utilization: Math.round(usedMem / totalMem * 100)
|
|
26243
|
+
},
|
|
26244
|
+
gpu,
|
|
26245
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
26246
|
+
};
|
|
26247
|
+
}
|
|
26205
26248
|
var DEFAULT_TARGETS, ExposeGateway;
|
|
26206
26249
|
var init_expose = __esm({
|
|
26207
26250
|
"packages/cli/dist/tui/expose.js"() {
|
|
@@ -26300,6 +26343,18 @@ var init_expose = __esm({
|
|
|
26300
26343
|
this.emitStats();
|
|
26301
26344
|
return;
|
|
26302
26345
|
}
|
|
26346
|
+
if (url.pathname === "/v1/system/metrics" && req.method === "GET") {
|
|
26347
|
+
const metrics = collectSystemMetrics();
|
|
26348
|
+
const gatewayStats = {
|
|
26349
|
+
totalRequests: this._stats.totalRequests,
|
|
26350
|
+
activeConnections: this._stats.activeConnections,
|
|
26351
|
+
errors: this._stats.errors,
|
|
26352
|
+
modelUsage: Object.fromEntries(this._stats.modelUsage)
|
|
26353
|
+
};
|
|
26354
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
26355
|
+
res.end(JSON.stringify({ ...metrics, gateway: gatewayStats }));
|
|
26356
|
+
return;
|
|
26357
|
+
}
|
|
26303
26358
|
this._stats.totalRequests++;
|
|
26304
26359
|
this._stats.activeConnections++;
|
|
26305
26360
|
this.emitStats();
|
|
@@ -28563,7 +28618,7 @@ var init_oa_directory = __esm({
|
|
|
28563
28618
|
|
|
28564
28619
|
// packages/cli/dist/tui/setup.js
|
|
28565
28620
|
import * as readline from "node:readline";
|
|
28566
|
-
import { execSync as
|
|
28621
|
+
import { execSync as execSync26, spawn as spawn15 } from "node:child_process";
|
|
28567
28622
|
import { existsSync as existsSync29, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
28568
28623
|
import { join as join39 } from "node:path";
|
|
28569
28624
|
import { homedir as homedir10, platform } from "node:os";
|
|
@@ -28573,7 +28628,7 @@ function detectSystemSpecs() {
|
|
|
28573
28628
|
let gpuVramGB = 0;
|
|
28574
28629
|
let gpuName = "";
|
|
28575
28630
|
try {
|
|
28576
|
-
const memInfo =
|
|
28631
|
+
const memInfo = execSync26("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
28577
28632
|
encoding: "utf8",
|
|
28578
28633
|
timeout: 5e3
|
|
28579
28634
|
});
|
|
@@ -28593,7 +28648,7 @@ function detectSystemSpecs() {
|
|
|
28593
28648
|
} catch {
|
|
28594
28649
|
}
|
|
28595
28650
|
try {
|
|
28596
|
-
const nvidiaSmi =
|
|
28651
|
+
const nvidiaSmi = execSync26("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
28597
28652
|
const lines = nvidiaSmi.trim().split("\n");
|
|
28598
28653
|
if (lines.length > 0) {
|
|
28599
28654
|
for (const line of lines) {
|
|
@@ -28718,7 +28773,7 @@ function ensureCurl() {
|
|
|
28718
28773
|
for (const s of strategies) {
|
|
28719
28774
|
if (hasCmd(s.check)) {
|
|
28720
28775
|
try {
|
|
28721
|
-
|
|
28776
|
+
execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
28722
28777
|
if (hasCmd("curl")) {
|
|
28723
28778
|
process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
|
|
28724
28779
|
`);
|
|
@@ -28732,7 +28787,7 @@ function ensureCurl() {
|
|
|
28732
28787
|
}
|
|
28733
28788
|
if (plat === "darwin") {
|
|
28734
28789
|
try {
|
|
28735
|
-
|
|
28790
|
+
execSync26("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
|
|
28736
28791
|
if (hasCmd("curl"))
|
|
28737
28792
|
return true;
|
|
28738
28793
|
} catch {
|
|
@@ -28767,7 +28822,7 @@ function installOllamaLinux() {
|
|
|
28767
28822
|
|
|
28768
28823
|
`);
|
|
28769
28824
|
try {
|
|
28770
|
-
|
|
28825
|
+
execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
28771
28826
|
stdio: "inherit",
|
|
28772
28827
|
timeout: 3e5
|
|
28773
28828
|
});
|
|
@@ -28795,7 +28850,7 @@ async function installOllamaMac(_rl) {
|
|
|
28795
28850
|
|
|
28796
28851
|
`);
|
|
28797
28852
|
try {
|
|
28798
|
-
|
|
28853
|
+
execSync26('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
28799
28854
|
if (!hasCmd("brew")) {
|
|
28800
28855
|
try {
|
|
28801
28856
|
const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
@@ -28828,7 +28883,7 @@ async function installOllamaMac(_rl) {
|
|
|
28828
28883
|
|
|
28829
28884
|
`);
|
|
28830
28885
|
try {
|
|
28831
|
-
|
|
28886
|
+
execSync26("brew install ollama", {
|
|
28832
28887
|
stdio: "inherit",
|
|
28833
28888
|
timeout: 3e5
|
|
28834
28889
|
});
|
|
@@ -28855,7 +28910,7 @@ function installOllamaWindows() {
|
|
|
28855
28910
|
|
|
28856
28911
|
`);
|
|
28857
28912
|
try {
|
|
28858
|
-
|
|
28913
|
+
execSync26('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
28859
28914
|
stdio: "inherit",
|
|
28860
28915
|
timeout: 3e5
|
|
28861
28916
|
});
|
|
@@ -28936,7 +28991,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
28936
28991
|
}
|
|
28937
28992
|
function pullModelWithAutoUpdate(tag) {
|
|
28938
28993
|
try {
|
|
28939
|
-
|
|
28994
|
+
execSync26(`ollama pull ${tag}`, {
|
|
28940
28995
|
stdio: "inherit",
|
|
28941
28996
|
timeout: 36e5
|
|
28942
28997
|
// 1 hour max
|
|
@@ -28956,7 +29011,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
28956
29011
|
|
|
28957
29012
|
`);
|
|
28958
29013
|
try {
|
|
28959
|
-
|
|
29014
|
+
execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
28960
29015
|
stdio: "inherit",
|
|
28961
29016
|
timeout: 3e5
|
|
28962
29017
|
// 5 min max for install
|
|
@@ -28967,7 +29022,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
28967
29022
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
28968
29023
|
|
|
28969
29024
|
`);
|
|
28970
|
-
|
|
29025
|
+
execSync26(`ollama pull ${tag}`, {
|
|
28971
29026
|
stdio: "inherit",
|
|
28972
29027
|
timeout: 36e5
|
|
28973
29028
|
});
|
|
@@ -29069,7 +29124,7 @@ function ensurePython3() {
|
|
|
29069
29124
|
if (plat === "darwin") {
|
|
29070
29125
|
if (hasCmd("brew")) {
|
|
29071
29126
|
try {
|
|
29072
|
-
|
|
29127
|
+
execSync26("brew install python3", { stdio: "inherit", timeout: 3e5 });
|
|
29073
29128
|
if (hasCmd("python3")) {
|
|
29074
29129
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
|
|
29075
29130
|
`);
|
|
@@ -29082,7 +29137,7 @@ function ensurePython3() {
|
|
|
29082
29137
|
for (const s of strategies) {
|
|
29083
29138
|
if (hasCmd(s.check)) {
|
|
29084
29139
|
try {
|
|
29085
|
-
|
|
29140
|
+
execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
29086
29141
|
if (hasCmd("python3") || hasCmd("python")) {
|
|
29087
29142
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
|
|
29088
29143
|
`);
|
|
@@ -29098,11 +29153,11 @@ function ensurePython3() {
|
|
|
29098
29153
|
}
|
|
29099
29154
|
function checkPythonVenv() {
|
|
29100
29155
|
try {
|
|
29101
|
-
|
|
29156
|
+
execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
29102
29157
|
return true;
|
|
29103
29158
|
} catch {
|
|
29104
29159
|
try {
|
|
29105
|
-
|
|
29160
|
+
execSync26("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
29106
29161
|
return true;
|
|
29107
29162
|
} catch {
|
|
29108
29163
|
return false;
|
|
@@ -29121,7 +29176,7 @@ function ensurePythonVenv() {
|
|
|
29121
29176
|
for (const s of strategies) {
|
|
29122
29177
|
if (hasCmd(s.check)) {
|
|
29123
29178
|
try {
|
|
29124
|
-
|
|
29179
|
+
execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
29125
29180
|
if (checkPythonVenv()) {
|
|
29126
29181
|
process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
|
|
29127
29182
|
`);
|
|
@@ -29557,7 +29612,7 @@ async function doSetup(config, rl) {
|
|
|
29557
29612
|
const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
|
|
29558
29613
|
writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
|
|
29559
29614
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
29560
|
-
|
|
29615
|
+
execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
29561
29616
|
stdio: "pipe",
|
|
29562
29617
|
timeout: 12e4
|
|
29563
29618
|
});
|
|
@@ -29608,7 +29663,7 @@ function isFirstRun() {
|
|
|
29608
29663
|
function hasCmd(cmd) {
|
|
29609
29664
|
try {
|
|
29610
29665
|
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
29611
|
-
|
|
29666
|
+
execSync26(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
29612
29667
|
return true;
|
|
29613
29668
|
} catch {
|
|
29614
29669
|
return false;
|
|
@@ -29641,7 +29696,7 @@ function getVenvDir() {
|
|
|
29641
29696
|
}
|
|
29642
29697
|
function hasVenvModule() {
|
|
29643
29698
|
try {
|
|
29644
|
-
|
|
29699
|
+
execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
29645
29700
|
return true;
|
|
29646
29701
|
} catch {
|
|
29647
29702
|
return false;
|
|
@@ -29663,8 +29718,8 @@ function ensureVenv(log) {
|
|
|
29663
29718
|
}
|
|
29664
29719
|
try {
|
|
29665
29720
|
mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
|
|
29666
|
-
|
|
29667
|
-
|
|
29721
|
+
execSync26(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
29722
|
+
execSync26(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
29668
29723
|
stdio: "pipe",
|
|
29669
29724
|
timeout: 6e4
|
|
29670
29725
|
});
|
|
@@ -29677,7 +29732,7 @@ function ensureVenv(log) {
|
|
|
29677
29732
|
}
|
|
29678
29733
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
29679
29734
|
try {
|
|
29680
|
-
|
|
29735
|
+
execSync26(`sudo -n ${cmd}`, {
|
|
29681
29736
|
stdio: "pipe",
|
|
29682
29737
|
timeout: timeoutMs,
|
|
29683
29738
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -29689,7 +29744,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
29689
29744
|
}
|
|
29690
29745
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
29691
29746
|
try {
|
|
29692
|
-
|
|
29747
|
+
execSync26(`sudo -S ${cmd}`, {
|
|
29693
29748
|
input: password + "\n",
|
|
29694
29749
|
stdio: ["pipe", "pipe", "pipe"],
|
|
29695
29750
|
timeout: timeoutMs,
|
|
@@ -29796,7 +29851,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29796
29851
|
ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
|
|
29797
29852
|
} else {
|
|
29798
29853
|
try {
|
|
29799
|
-
|
|
29854
|
+
execSync26(batchCmd, { stdio: "pipe", timeout: 18e4 });
|
|
29800
29855
|
ok = true;
|
|
29801
29856
|
} catch {
|
|
29802
29857
|
ok = false;
|
|
@@ -29833,7 +29888,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29833
29888
|
const venvCmds = {
|
|
29834
29889
|
apt: () => {
|
|
29835
29890
|
try {
|
|
29836
|
-
const pyVer =
|
|
29891
|
+
const pyVer = execSync26(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
29837
29892
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
29838
29893
|
} catch {
|
|
29839
29894
|
return "apt-get install -y python3-venv";
|
|
@@ -29861,12 +29916,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29861
29916
|
const venvPip = join39(venvBin, "pip");
|
|
29862
29917
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
29863
29918
|
try {
|
|
29864
|
-
|
|
29919
|
+
execSync26(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
29865
29920
|
if (existsSync29(venvMoondream)) {
|
|
29866
29921
|
log("moondream-station installed successfully.");
|
|
29867
29922
|
} else {
|
|
29868
29923
|
try {
|
|
29869
|
-
const check =
|
|
29924
|
+
const check = execSync26(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
29870
29925
|
if (check.includes("moondream")) {
|
|
29871
29926
|
log("moondream-station package installed.");
|
|
29872
29927
|
}
|
|
@@ -29883,7 +29938,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29883
29938
|
const venvPip2 = join39(venvBin, "pip");
|
|
29884
29939
|
let ocrStackInstalled = false;
|
|
29885
29940
|
try {
|
|
29886
|
-
|
|
29941
|
+
execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
29887
29942
|
ocrStackInstalled = true;
|
|
29888
29943
|
} catch {
|
|
29889
29944
|
}
|
|
@@ -29891,9 +29946,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29891
29946
|
const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
|
|
29892
29947
|
log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
|
|
29893
29948
|
try {
|
|
29894
|
-
|
|
29949
|
+
execSync26(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
|
|
29895
29950
|
try {
|
|
29896
|
-
|
|
29951
|
+
execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
29897
29952
|
log("OCR Python stack installed successfully.");
|
|
29898
29953
|
} catch {
|
|
29899
29954
|
log("OCR Python stack install completed but import verification failed.");
|
|
@@ -29927,7 +29982,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
29927
29982
|
const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
|
|
29928
29983
|
const cfArch = archMap[arch] ?? "amd64";
|
|
29929
29984
|
try {
|
|
29930
|
-
|
|
29985
|
+
execSync26(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
|
|
29931
29986
|
if (!process.env.PATH?.includes(`${homedir10()}/.local/bin`)) {
|
|
29932
29987
|
process.env.PATH = `${homedir10()}/.local/bin:${process.env.PATH}`;
|
|
29933
29988
|
}
|
|
@@ -29938,7 +29993,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
29938
29993
|
} catch {
|
|
29939
29994
|
}
|
|
29940
29995
|
try {
|
|
29941
|
-
|
|
29996
|
+
execSync26(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
|
|
29942
29997
|
if (hasCmd("cloudflared")) {
|
|
29943
29998
|
log("cloudflared installed.");
|
|
29944
29999
|
return true;
|
|
@@ -29947,7 +30002,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
29947
30002
|
}
|
|
29948
30003
|
} else if (os === "darwin") {
|
|
29949
30004
|
try {
|
|
29950
|
-
|
|
30005
|
+
execSync26("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
|
|
29951
30006
|
if (hasCmd("cloudflared")) {
|
|
29952
30007
|
log("cloudflared installed via Homebrew.");
|
|
29953
30008
|
return true;
|
|
@@ -29997,7 +30052,7 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
29997
30052
|
mkdirSync10(modelDir2, { recursive: true });
|
|
29998
30053
|
const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
|
|
29999
30054
|
writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
|
|
30000
|
-
|
|
30055
|
+
execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
30001
30056
|
stdio: "pipe",
|
|
30002
30057
|
timeout: 12e4
|
|
30003
30058
|
});
|
|
@@ -30086,12 +30141,24 @@ function ansi3(code, text) {
|
|
|
30086
30141
|
function fg2562(code, text) {
|
|
30087
30142
|
return isTTY3 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
|
|
30088
30143
|
}
|
|
30144
|
+
function stripAnsi(s) {
|
|
30145
|
+
return s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
30146
|
+
}
|
|
30089
30147
|
function defaultRenderRow(item, focused, isActive) {
|
|
30090
30148
|
const marker = isActive ? selectColors.green("\u25CF") : focused ? selectColors.orange("\u25CF") : selectColors.dim("\u25CB");
|
|
30091
30149
|
const label = focused ? selectColors.orange(selectColors.bold(item.label)) : isActive ? selectColors.green(item.label) : item.label;
|
|
30092
30150
|
const detail = item.detail ? ` ${selectColors.dim(item.detail)}` : "";
|
|
30093
30151
|
return ` ${marker} ${label}${detail}`;
|
|
30094
30152
|
}
|
|
30153
|
+
function matchRow(item, focused, isActive) {
|
|
30154
|
+
if (focused || isActive) {
|
|
30155
|
+
return defaultRenderRow(item, focused, isActive);
|
|
30156
|
+
}
|
|
30157
|
+
const marker = selectColors.matchLight("\u25CB");
|
|
30158
|
+
const label = selectColors.matchLight(stripAnsi(item.label));
|
|
30159
|
+
const detail = item.detail ? ` ${selectColors.dim(stripAnsi(item.detail))}` : "";
|
|
30160
|
+
return ` ${marker} ${label}${detail}`;
|
|
30161
|
+
}
|
|
30095
30162
|
function tuiSelect(opts) {
|
|
30096
30163
|
const { items, title, rl } = opts;
|
|
30097
30164
|
const renderRow = opts.renderRow ?? defaultRenderRow;
|
|
@@ -30101,20 +30168,44 @@ function tuiSelect(opts) {
|
|
|
30101
30168
|
return Promise.resolve({ confirmed: false, key: null, index: -1 });
|
|
30102
30169
|
}
|
|
30103
30170
|
const isSkippable = (idx) => skipSet.has(items[idx].key);
|
|
30171
|
+
let filter = "";
|
|
30172
|
+
let matchSet = /* @__PURE__ */ new Set();
|
|
30173
|
+
function updateFilter() {
|
|
30174
|
+
if (!filter) {
|
|
30175
|
+
matchSet = new Set(items.map((_, i) => i));
|
|
30176
|
+
} else {
|
|
30177
|
+
const lower = filter.toLowerCase();
|
|
30178
|
+
matchSet = /* @__PURE__ */ new Set();
|
|
30179
|
+
for (let i = 0; i < items.length; i++) {
|
|
30180
|
+
if (isSkippable(i))
|
|
30181
|
+
continue;
|
|
30182
|
+
const plain = stripAnsi(items[i].label).toLowerCase();
|
|
30183
|
+
const detailPlain = items[i].detail ? stripAnsi(items[i].detail).toLowerCase() : "";
|
|
30184
|
+
if (plain.includes(lower) || detailPlain.includes(lower)) {
|
|
30185
|
+
matchSet.add(i);
|
|
30186
|
+
}
|
|
30187
|
+
}
|
|
30188
|
+
}
|
|
30189
|
+
}
|
|
30190
|
+
updateFilter();
|
|
30104
30191
|
const findSelectable = (from, dir) => {
|
|
30105
30192
|
let idx = from;
|
|
30106
|
-
while (idx >= 0 && idx < items.length
|
|
30193
|
+
while (idx >= 0 && idx < items.length) {
|
|
30194
|
+
if (!isSkippable(idx) && matchSet.has(idx))
|
|
30195
|
+
return idx;
|
|
30107
30196
|
idx += dir;
|
|
30108
30197
|
}
|
|
30109
|
-
return
|
|
30198
|
+
return -1;
|
|
30110
30199
|
};
|
|
30111
|
-
let cursor = activeKey ? items.findIndex((i) => i.key === activeKey) :
|
|
30112
|
-
if (cursor < 0)
|
|
30113
|
-
|
|
30114
|
-
|
|
30200
|
+
let cursor = activeKey ? items.findIndex((i) => i.key === activeKey) : -1;
|
|
30201
|
+
if (cursor < 0 || isSkippable(cursor)) {
|
|
30202
|
+
const first = findSelectable(0, 1);
|
|
30203
|
+
cursor = first >= 0 ? first : 0;
|
|
30204
|
+
}
|
|
30115
30205
|
const termRows = process.stdout.rows ?? 24;
|
|
30116
|
-
const
|
|
30117
|
-
|
|
30206
|
+
const overhead = 6;
|
|
30207
|
+
const maxVisible = opts.maxVisible ?? Math.max(3, termRows - overhead);
|
|
30208
|
+
let scrollOffset = 0;
|
|
30118
30209
|
let lastRenderedLines = 0;
|
|
30119
30210
|
return new Promise((resolve31) => {
|
|
30120
30211
|
const stdin = process.stdin;
|
|
@@ -30135,15 +30226,17 @@ function tuiSelect(opts) {
|
|
|
30135
30226
|
}
|
|
30136
30227
|
stdin.resume();
|
|
30137
30228
|
process.stdout.write("\x1B[?25l");
|
|
30138
|
-
function clampScroll() {
|
|
30139
|
-
|
|
30140
|
-
|
|
30141
|
-
|
|
30142
|
-
|
|
30143
|
-
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30229
|
+
function clampScroll(displayList) {
|
|
30230
|
+
const cursorPos = displayList.indexOf(cursor);
|
|
30231
|
+
if (cursorPos < 0)
|
|
30232
|
+
return;
|
|
30233
|
+
if (cursorPos < scrollOffset) {
|
|
30234
|
+
scrollOffset = cursorPos;
|
|
30235
|
+
} else if (cursorPos >= scrollOffset + maxVisible) {
|
|
30236
|
+
scrollOffset = cursorPos - maxVisible + 1;
|
|
30237
|
+
}
|
|
30238
|
+
const maxOffset = Math.max(0, displayList.length - maxVisible);
|
|
30239
|
+
scrollOffset = Math.max(0, Math.min(maxOffset, scrollOffset));
|
|
30147
30240
|
}
|
|
30148
30241
|
function render() {
|
|
30149
30242
|
if (lastRenderedLines > 0) {
|
|
@@ -30153,33 +30246,67 @@ function tuiSelect(opts) {
|
|
|
30153
30246
|
}
|
|
30154
30247
|
process.stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
30155
30248
|
}
|
|
30156
|
-
clampScroll();
|
|
30157
30249
|
const lines = [];
|
|
30158
30250
|
if (title) {
|
|
30159
30251
|
lines.push(`
|
|
30160
30252
|
${selectColors.bold(title)}`);
|
|
30161
|
-
lines.push("");
|
|
30162
30253
|
}
|
|
30163
|
-
if (
|
|
30164
|
-
|
|
30254
|
+
if (filter) {
|
|
30255
|
+
const count = matchSet.size;
|
|
30256
|
+
lines.push(` ${selectColors.cyan("/")} ${selectColors.bold(filter)} ${selectColors.dim(`(${count} match${count !== 1 ? "es" : ""})`)}`);
|
|
30257
|
+
} else {
|
|
30258
|
+
lines.push(` ${selectColors.dim("Type to filter...")}`);
|
|
30165
30259
|
}
|
|
30166
|
-
|
|
30167
|
-
|
|
30168
|
-
|
|
30169
|
-
|
|
30260
|
+
lines.push("");
|
|
30261
|
+
let displayList;
|
|
30262
|
+
if (filter) {
|
|
30263
|
+
displayList = [];
|
|
30264
|
+
for (let i = 0; i < items.length; i++) {
|
|
30265
|
+
if (matchSet.has(i) || isSkippable(i)) {
|
|
30266
|
+
displayList.push(i);
|
|
30267
|
+
}
|
|
30268
|
+
}
|
|
30269
|
+
displayList = displayList.filter((idx, pos) => {
|
|
30270
|
+
if (!isSkippable(idx))
|
|
30271
|
+
return true;
|
|
30272
|
+
for (let j = pos + 1; j < displayList.length; j++) {
|
|
30273
|
+
if (!isSkippable(displayList[j]))
|
|
30274
|
+
return true;
|
|
30275
|
+
break;
|
|
30276
|
+
}
|
|
30277
|
+
return false;
|
|
30278
|
+
});
|
|
30279
|
+
} else {
|
|
30280
|
+
displayList = items.map((_, i) => i);
|
|
30281
|
+
}
|
|
30282
|
+
clampScroll(displayList);
|
|
30283
|
+
const visibleStart = scrollOffset;
|
|
30284
|
+
const visibleEnd = Math.min(displayList.length, scrollOffset + maxVisible);
|
|
30285
|
+
if (visibleStart > 0) {
|
|
30286
|
+
lines.push(` ${selectColors.dim(` \u25B2 ${visibleStart} more`)}`);
|
|
30287
|
+
}
|
|
30288
|
+
for (let vi = visibleStart; vi < visibleEnd; vi++) {
|
|
30289
|
+
const idx = displayList[vi];
|
|
30290
|
+
const item = items[idx];
|
|
30291
|
+
if (isSkippable(idx)) {
|
|
30170
30292
|
lines.push(` ${item.label}`);
|
|
30171
30293
|
continue;
|
|
30172
30294
|
}
|
|
30173
|
-
const focused =
|
|
30295
|
+
const focused = idx === cursor;
|
|
30174
30296
|
const isActive = item.key === activeKey;
|
|
30175
|
-
|
|
30297
|
+
if (filter) {
|
|
30298
|
+
lines.push(matchRow(item, focused, isActive));
|
|
30299
|
+
} else {
|
|
30300
|
+
lines.push(renderRow(item, focused, isActive));
|
|
30301
|
+
}
|
|
30176
30302
|
}
|
|
30177
|
-
const remaining =
|
|
30303
|
+
const remaining = displayList.length - visibleEnd;
|
|
30178
30304
|
if (remaining > 0) {
|
|
30179
30305
|
lines.push(` ${selectColors.dim(` \u25BC ${remaining} more`)}`);
|
|
30180
30306
|
}
|
|
30181
30307
|
lines.push("");
|
|
30182
|
-
|
|
30308
|
+
const actionHint = opts.onAction ? " \u2190/\u2192/Space toggle" : "";
|
|
30309
|
+
lines.push(` ${selectColors.dim("\u2191/\u2193 navigate Enter select" + actionHint + " Esc " + (filter ? "clear filter" : "cancel") + " Type to filter")}`);
|
|
30183
30310
|
lines.push("");
|
|
30184
30311
|
const output = lines.join("\n");
|
|
30185
30312
|
process.stdout.write(output);
|
|
@@ -30187,6 +30314,7 @@ function tuiSelect(opts) {
|
|
|
30187
30314
|
}
|
|
30188
30315
|
function cleanup() {
|
|
30189
30316
|
stdin.removeListener("data", onData);
|
|
30317
|
+
process.stdout.removeListener("resize", onResize);
|
|
30190
30318
|
process.stdout.write("\x1B[?25h");
|
|
30191
30319
|
if (lastRenderedLines > 0) {
|
|
30192
30320
|
process.stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
@@ -30208,37 +30336,108 @@ function tuiSelect(opts) {
|
|
|
30208
30336
|
}
|
|
30209
30337
|
function onData(chunk) {
|
|
30210
30338
|
const seq = chunk.toString("utf8");
|
|
30211
|
-
if (seq === "\x1B[A"
|
|
30212
|
-
const next = cursor - 1;
|
|
30213
|
-
if (next >= 0) {
|
|
30214
|
-
cursor =
|
|
30339
|
+
if (seq === "\x1B[A") {
|
|
30340
|
+
const next = findSelectable(cursor - 1, -1);
|
|
30341
|
+
if (next >= 0 && next !== cursor) {
|
|
30342
|
+
cursor = next;
|
|
30215
30343
|
render();
|
|
30216
30344
|
}
|
|
30217
|
-
} else if (seq === "\x1B[B"
|
|
30218
|
-
const next = cursor + 1;
|
|
30219
|
-
if (next
|
|
30220
|
-
cursor =
|
|
30345
|
+
} else if (seq === "\x1B[B") {
|
|
30346
|
+
const next = findSelectable(cursor + 1, 1);
|
|
30347
|
+
if (next >= 0 && next !== cursor) {
|
|
30348
|
+
cursor = next;
|
|
30221
30349
|
render();
|
|
30222
30350
|
}
|
|
30223
|
-
} else if (seq === "\x1B[
|
|
30224
|
-
|
|
30351
|
+
} else if (seq === "\x1B[5~") {
|
|
30352
|
+
for (let i = 0; i < maxVisible; i++) {
|
|
30353
|
+
const next = findSelectable(cursor - 1, -1);
|
|
30354
|
+
if (next < 0 || next === cursor)
|
|
30355
|
+
break;
|
|
30356
|
+
cursor = next;
|
|
30357
|
+
}
|
|
30225
30358
|
render();
|
|
30226
|
-
} else if (seq === "\x1B[
|
|
30227
|
-
|
|
30359
|
+
} else if (seq === "\x1B[6~") {
|
|
30360
|
+
for (let i = 0; i < maxVisible; i++) {
|
|
30361
|
+
const next = findSelectable(cursor + 1, 1);
|
|
30362
|
+
if (next < 0 || next === cursor)
|
|
30363
|
+
break;
|
|
30364
|
+
cursor = next;
|
|
30365
|
+
}
|
|
30228
30366
|
render();
|
|
30367
|
+
} else if (seq === "\x1B[H") {
|
|
30368
|
+
const first = findSelectable(0, 1);
|
|
30369
|
+
if (first >= 0) {
|
|
30370
|
+
cursor = first;
|
|
30371
|
+
render();
|
|
30372
|
+
}
|
|
30373
|
+
} else if (seq === "\x1B[F") {
|
|
30374
|
+
const last = findSelectable(items.length - 1, -1);
|
|
30375
|
+
if (last >= 0) {
|
|
30376
|
+
cursor = last;
|
|
30377
|
+
render();
|
|
30378
|
+
}
|
|
30379
|
+
} else if (seq === "\x1B[D" && opts.onAction) {
|
|
30380
|
+
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
30381
|
+
if (opts.onAction(items[cursor], "left"))
|
|
30382
|
+
render();
|
|
30383
|
+
}
|
|
30384
|
+
} else if (seq === "\x1B[C" && opts.onAction) {
|
|
30385
|
+
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
30386
|
+
if (opts.onAction(items[cursor], "right"))
|
|
30387
|
+
render();
|
|
30388
|
+
}
|
|
30389
|
+
} else if (seq === " " && opts.onAction) {
|
|
30390
|
+
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
30391
|
+
if (opts.onAction(items[cursor], "space"))
|
|
30392
|
+
render();
|
|
30393
|
+
}
|
|
30229
30394
|
} else if (seq === "\r" || seq === "\n") {
|
|
30230
|
-
if (!isSkippable(cursor)) {
|
|
30395
|
+
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
30231
30396
|
cleanup();
|
|
30232
30397
|
resolve31({ confirmed: true, key: items[cursor].key, index: cursor });
|
|
30233
30398
|
}
|
|
30234
|
-
} else if (seq === "\x1B" || seq === "\x1B\x1B"
|
|
30235
|
-
|
|
30236
|
-
|
|
30399
|
+
} else if (seq === "\x1B" || seq === "\x1B\x1B") {
|
|
30400
|
+
if (filter) {
|
|
30401
|
+
filter = "";
|
|
30402
|
+
updateFilter();
|
|
30403
|
+
const valid = findSelectable(cursor, 1);
|
|
30404
|
+
if (valid >= 0)
|
|
30405
|
+
cursor = valid;
|
|
30406
|
+
scrollOffset = 0;
|
|
30407
|
+
render();
|
|
30408
|
+
} else {
|
|
30409
|
+
cleanup();
|
|
30410
|
+
resolve31({ confirmed: false, key: null, index: cursor });
|
|
30411
|
+
}
|
|
30237
30412
|
} else if (seq === "") {
|
|
30238
30413
|
cleanup();
|
|
30239
30414
|
resolve31({ confirmed: false, key: null, index: cursor });
|
|
30415
|
+
} else if (seq === "\x7F" || seq === "\b") {
|
|
30416
|
+
if (filter.length > 0) {
|
|
30417
|
+
filter = filter.slice(0, -1);
|
|
30418
|
+
updateFilter();
|
|
30419
|
+
if (!matchSet.has(cursor) || isSkippable(cursor)) {
|
|
30420
|
+
const next = findSelectable(0, 1);
|
|
30421
|
+
if (next >= 0)
|
|
30422
|
+
cursor = next;
|
|
30423
|
+
}
|
|
30424
|
+
scrollOffset = 0;
|
|
30425
|
+
render();
|
|
30426
|
+
}
|
|
30427
|
+
} else if (seq.length === 1 && seq.charCodeAt(0) >= 32 && seq.charCodeAt(0) < 127) {
|
|
30428
|
+
filter += seq;
|
|
30429
|
+
updateFilter();
|
|
30430
|
+
if (matchSet.size > 0) {
|
|
30431
|
+
const first = findSelectable(0, 1);
|
|
30432
|
+
if (first >= 0)
|
|
30433
|
+
cursor = first;
|
|
30434
|
+
}
|
|
30435
|
+
scrollOffset = 0;
|
|
30436
|
+
render();
|
|
30240
30437
|
}
|
|
30241
30438
|
}
|
|
30439
|
+
const onResize = () => render();
|
|
30440
|
+
process.stdout.on("resize", onResize);
|
|
30242
30441
|
stdin.on("data", onData);
|
|
30243
30442
|
render();
|
|
30244
30443
|
});
|
|
@@ -30253,7 +30452,11 @@ var init_tui_select = __esm({
|
|
|
30253
30452
|
green: (t) => ansi3("32", t),
|
|
30254
30453
|
dim: (t) => ansi3("2", t),
|
|
30255
30454
|
bold: (t) => ansi3("1", t),
|
|
30256
|
-
cyan: (t) => ansi3("36", t)
|
|
30455
|
+
cyan: (t) => ansi3("36", t),
|
|
30456
|
+
/** Lighter grey for filter matches (252 = near-white) */
|
|
30457
|
+
matchLight: (t) => fg2562(252, t),
|
|
30458
|
+
/** Dark grey for non-matching items (240 = dark grey) */
|
|
30459
|
+
matchDark: (t) => fg2562(240, t)
|
|
30257
30460
|
};
|
|
30258
30461
|
}
|
|
30259
30462
|
});
|
|
@@ -30294,38 +30497,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
30294
30497
|
return "handled";
|
|
30295
30498
|
case "config":
|
|
30296
30499
|
case "cfg": {
|
|
30297
|
-
|
|
30298
|
-
const globalS = loadGlobalSettings();
|
|
30299
|
-
const merged = { ...globalS, ...resolved };
|
|
30300
|
-
renderConfig({
|
|
30301
|
-
// -- Core inference --
|
|
30302
|
-
model: ctx.config.model,
|
|
30303
|
-
backendType: ctx.config.backendType,
|
|
30304
|
-
backendUrl: ctx.config.backendUrl,
|
|
30305
|
-
apiKey: ctx.config.apiKey ? "[set]" : "[not set]",
|
|
30306
|
-
maxRetries: String(ctx.config.maxRetries),
|
|
30307
|
-
timeoutMs: String(ctx.config.timeoutMs),
|
|
30308
|
-
dbPath: ctx.config.dbPath,
|
|
30309
|
-
// -- Behaviour --
|
|
30310
|
-
dryRun: String(ctx.config.dryRun),
|
|
30311
|
-
verbose: String(ctx.config.verbose),
|
|
30312
|
-
stream: String(merged.stream ?? false),
|
|
30313
|
-
bruteforce: String(merged.bruteforce ?? false),
|
|
30314
|
-
deepContext: String(merged.deepContext ?? false),
|
|
30315
|
-
// -- Presentation --
|
|
30316
|
-
emojis: String(ctx.getEmojis?.() ?? merged.emojis ?? true),
|
|
30317
|
-
colors: String(ctx.getColors?.() ?? merged.colors ?? true),
|
|
30318
|
-
style: String(ctx.getStyle?.() ?? merged.style ?? "balanced"),
|
|
30319
|
-
// -- Voice --
|
|
30320
|
-
voice: String(merged.voice ?? false),
|
|
30321
|
-
voiceModel: String(merged.voiceModel ?? "glados"),
|
|
30322
|
-
// -- Autonomy --
|
|
30323
|
-
commandsMode: String(ctx.getCommandsMode?.() ?? merged.commandsMode ?? "manual"),
|
|
30324
|
-
updateMode: String(merged.updateMode ?? "auto"),
|
|
30325
|
-
// -- Integrations --
|
|
30326
|
-
telegramKey: merged.telegramKey ? "[set]" : "[not set]",
|
|
30327
|
-
telegramAdmin: String(merged.telegramAdmin ?? "[not set]")
|
|
30328
|
-
});
|
|
30500
|
+
await showConfigEditor(ctx);
|
|
30329
30501
|
return "handled";
|
|
30330
30502
|
}
|
|
30331
30503
|
case "cost":
|
|
@@ -30739,25 +30911,26 @@ async function handleSlashCommand(input, ctx) {
|
|
|
30739
30911
|
}
|
|
30740
30912
|
case "commands":
|
|
30741
30913
|
case "cmds": {
|
|
30742
|
-
if (!ctx.getCommandsMode || !ctx.setCommandsMode) {
|
|
30743
|
-
renderWarning("Commands mode not available in this context.");
|
|
30744
|
-
return "handled";
|
|
30745
|
-
}
|
|
30746
30914
|
if (arg === "auto") {
|
|
30915
|
+
if (!ctx.setCommandsMode) {
|
|
30916
|
+
renderWarning("Commands mode not available.");
|
|
30917
|
+
return "handled";
|
|
30918
|
+
}
|
|
30747
30919
|
ctx.setCommandsMode("auto");
|
|
30748
30920
|
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30749
30921
|
save({ commandsMode: "auto" });
|
|
30750
30922
|
renderInfo("Commands mode: auto \u2014 the agent can now invoke slash commands as tools.");
|
|
30751
30923
|
} else if (arg === "manual") {
|
|
30924
|
+
if (!ctx.setCommandsMode) {
|
|
30925
|
+
renderWarning("Commands mode not available.");
|
|
30926
|
+
return "handled";
|
|
30927
|
+
}
|
|
30752
30928
|
ctx.setCommandsMode("manual");
|
|
30753
30929
|
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30754
30930
|
save({ commandsMode: "manual" });
|
|
30755
30931
|
renderInfo("Commands mode: manual \u2014 slash commands are user-only.");
|
|
30756
30932
|
} else {
|
|
30757
|
-
|
|
30758
|
-
renderInfo(`Commands mode: ${c2.bold(current)}`);
|
|
30759
|
-
renderInfo(" /commands auto \u2014 agent can invoke slash commands as tools");
|
|
30760
|
-
renderInfo(" /commands manual \u2014 slash commands are user-only (default)");
|
|
30933
|
+
renderSlashHelp();
|
|
30761
30934
|
}
|
|
30762
30935
|
return "handled";
|
|
30763
30936
|
}
|
|
@@ -31364,6 +31537,162 @@ async function handleSlashCommand(input, ctx) {
|
|
|
31364
31537
|
}
|
|
31365
31538
|
}
|
|
31366
31539
|
}
|
|
31540
|
+
async function showConfigEditor(ctx) {
|
|
31541
|
+
const merged = { ...loadGlobalSettings(), ...loadProjectSettings(ctx.repoRoot) };
|
|
31542
|
+
const pendingChanges = {};
|
|
31543
|
+
let hasChanges = false;
|
|
31544
|
+
const entries = [
|
|
31545
|
+
// -- Headers & categories --
|
|
31546
|
+
{ key: "__h_core__", label: c2.dim("\u2500\u2500 Core Inference \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31547
|
+
{ key: "model", label: "model", kind: "readonly", value: ctx.config.model, detail: ctx.config.model },
|
|
31548
|
+
{ key: "backendUrl", label: "backendUrl", kind: "readonly", value: ctx.config.backendUrl, detail: ctx.config.backendUrl },
|
|
31549
|
+
{ key: "backendType", label: "backendType", kind: "readonly", value: ctx.config.backendType, detail: ctx.config.backendType },
|
|
31550
|
+
{ key: "apiKey", label: "apiKey", kind: "readonly", value: ctx.config.apiKey ? "[set]" : "[not set]", detail: ctx.config.apiKey ? "[set]" : "[not set]" },
|
|
31551
|
+
{ key: "maxRetries", label: "maxRetries", kind: "string", value: String(ctx.config.maxRetries), detail: String(ctx.config.maxRetries), settingsKey: "maxRetries" },
|
|
31552
|
+
{ key: "timeoutMs", label: "timeoutMs", kind: "string", value: String(ctx.config.timeoutMs), detail: String(ctx.config.timeoutMs), settingsKey: "timeoutMs" },
|
|
31553
|
+
{ key: "__h_behav__", label: c2.dim("\u2500\u2500 Behaviour \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31554
|
+
{ key: "verbose", label: "verbose", kind: "boolean", value: String(ctx.config.verbose), detail: String(ctx.config.verbose), settingsKey: "verbose" },
|
|
31555
|
+
{ key: "stream", label: "stream", kind: "boolean", value: String(merged.stream ?? false), detail: String(merged.stream ?? false), settingsKey: "stream" },
|
|
31556
|
+
{ key: "bruteforce", label: "bruteforce", kind: "boolean", value: String(merged.bruteforce ?? false), detail: String(merged.bruteforce ?? false), settingsKey: "bruteforce" },
|
|
31557
|
+
{ key: "deepContext", label: "deepContext", kind: "boolean", value: String(merged.deepContext ?? false), detail: String(merged.deepContext ?? false), settingsKey: "deepContext" },
|
|
31558
|
+
{ key: "dryRun", label: "dryRun", kind: "boolean", value: String(ctx.config.dryRun), detail: String(ctx.config.dryRun), settingsKey: "dryRun" },
|
|
31559
|
+
{ key: "__h_pres__", label: c2.dim("\u2500\u2500 Presentation \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31560
|
+
{ key: "emojis", label: "emojis", kind: "boolean", value: String(ctx.getEmojis?.() ?? merged.emojis ?? true), detail: String(ctx.getEmojis?.() ?? merged.emojis ?? true), settingsKey: "emojis" },
|
|
31561
|
+
{ key: "colors", label: "colors", kind: "boolean", value: String(ctx.getColors?.() ?? merged.colors ?? true), detail: String(ctx.getColors?.() ?? merged.colors ?? true), settingsKey: "colors" },
|
|
31562
|
+
{ key: "style", label: "style", kind: "enum", value: String(ctx.getStyle?.() ?? merged.style ?? "balanced"), detail: String(ctx.getStyle?.() ?? merged.style ?? "balanced"), options: [...PRESET_NAMES], settingsKey: "style" },
|
|
31563
|
+
{ key: "__h_voice__", label: c2.dim("\u2500\u2500 Voice \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31564
|
+
{ key: "voice", label: "voice", kind: "boolean", value: String(merged.voice ?? false), detail: String(merged.voice ?? false), settingsKey: "voice" },
|
|
31565
|
+
{ key: "voiceModel", label: "voiceModel", kind: "enum", value: String(merged.voiceModel ?? "glados"), detail: String(merged.voiceModel ?? "glados"), options: ["glados", "overwatch"], settingsKey: "voiceModel" },
|
|
31566
|
+
{ key: "__h_auto__", label: c2.dim("\u2500\u2500 Autonomy \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31567
|
+
{ key: "commandsMode", label: "commandsMode", kind: "enum", value: String(ctx.getCommandsMode?.() ?? merged.commandsMode ?? "manual"), detail: String(ctx.getCommandsMode?.() ?? merged.commandsMode ?? "manual"), options: ["manual", "auto"], settingsKey: "commandsMode" },
|
|
31568
|
+
{ key: "updateMode", label: "updateMode", kind: "enum", value: String(merged.updateMode ?? "auto"), detail: String(merged.updateMode ?? "auto"), options: ["auto", "manual"], settingsKey: "updateMode" },
|
|
31569
|
+
{ key: "__h_int__", label: c2.dim("\u2500\u2500 Integrations \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31570
|
+
{ key: "telegramKey", label: "telegramKey", kind: "readonly", value: merged.telegramKey ? "[set]" : "[not set]", detail: merged.telegramKey ? "[set]" : "[not set]" },
|
|
31571
|
+
{ key: "telegramAdmin", label: "telegramAdmin", kind: "readonly", value: String(merged.telegramAdmin ?? "[not set]"), detail: String(merged.telegramAdmin ?? "[not set]") },
|
|
31572
|
+
// -- Actions --
|
|
31573
|
+
{ key: "__h_actions__", label: c2.dim("\u2500\u2500 Actions \u2500\u2500"), detail: "", kind: "header", value: "" },
|
|
31574
|
+
{ key: "__save_global__", label: c2.bold("Save to global settings"), detail: "~/.open-agents/settings.json", kind: "action", value: "save_global" },
|
|
31575
|
+
{ key: "__save_local__", label: c2.bold("Save to project settings"), detail: ".oa/settings.json", kind: "action", value: "save_local" }
|
|
31576
|
+
];
|
|
31577
|
+
function renderConfigRow(item, focused, _isActive) {
|
|
31578
|
+
if (item.kind === "header") {
|
|
31579
|
+
return ` ${item.label}`;
|
|
31580
|
+
}
|
|
31581
|
+
const marker = focused ? selectColors.orange("\u25CF") : selectColors.dim("\u25CB");
|
|
31582
|
+
const nameStr = focused ? selectColors.orange(selectColors.bold(item.label)) : item.label;
|
|
31583
|
+
if (item.kind === "action") {
|
|
31584
|
+
return ` ${marker} ${nameStr} ${selectColors.dim(item.detail ?? "")}`;
|
|
31585
|
+
}
|
|
31586
|
+
let valueStr;
|
|
31587
|
+
if (item.kind === "boolean") {
|
|
31588
|
+
const val = item.value === "true";
|
|
31589
|
+
valueStr = val ? selectColors.green("true") : c2.red("false");
|
|
31590
|
+
if (focused)
|
|
31591
|
+
valueStr += selectColors.dim(" \u2190/\u2192/Space toggle");
|
|
31592
|
+
} else if (item.kind === "enum") {
|
|
31593
|
+
valueStr = selectColors.cyan(item.value);
|
|
31594
|
+
if (focused && item.options) {
|
|
31595
|
+
const idx = item.options.indexOf(item.value);
|
|
31596
|
+
const prev = item.options[(idx - 1 + item.options.length) % item.options.length];
|
|
31597
|
+
const next = item.options[(idx + 1) % item.options.length];
|
|
31598
|
+
valueStr += selectColors.dim(` \u2190 ${prev} | ${next} \u2192`);
|
|
31599
|
+
}
|
|
31600
|
+
} else if (item.kind === "readonly") {
|
|
31601
|
+
valueStr = selectColors.dim(item.value);
|
|
31602
|
+
} else {
|
|
31603
|
+
valueStr = item.value;
|
|
31604
|
+
if (focused)
|
|
31605
|
+
valueStr += selectColors.dim(" Enter to edit");
|
|
31606
|
+
}
|
|
31607
|
+
return ` ${marker} ${nameStr.padEnd(focused ? 20 : 20)} ${valueStr}`;
|
|
31608
|
+
}
|
|
31609
|
+
function onAction(item, action) {
|
|
31610
|
+
if (item.kind === "boolean") {
|
|
31611
|
+
const newVal = item.value === "true" ? "false" : "true";
|
|
31612
|
+
item.value = newVal;
|
|
31613
|
+
item.detail = newVal;
|
|
31614
|
+
if (item.settingsKey) {
|
|
31615
|
+
pendingChanges[item.settingsKey] = newVal === "true";
|
|
31616
|
+
}
|
|
31617
|
+
hasChanges = true;
|
|
31618
|
+
return true;
|
|
31619
|
+
}
|
|
31620
|
+
if (item.kind === "enum" && item.options) {
|
|
31621
|
+
const idx = item.options.indexOf(item.value);
|
|
31622
|
+
let newIdx;
|
|
31623
|
+
if (action === "left") {
|
|
31624
|
+
newIdx = (idx - 1 + item.options.length) % item.options.length;
|
|
31625
|
+
} else {
|
|
31626
|
+
newIdx = (idx + 1) % item.options.length;
|
|
31627
|
+
}
|
|
31628
|
+
item.value = item.options[newIdx];
|
|
31629
|
+
item.detail = item.value;
|
|
31630
|
+
if (item.settingsKey) {
|
|
31631
|
+
pendingChanges[item.settingsKey] = item.value;
|
|
31632
|
+
}
|
|
31633
|
+
hasChanges = true;
|
|
31634
|
+
return true;
|
|
31635
|
+
}
|
|
31636
|
+
return false;
|
|
31637
|
+
}
|
|
31638
|
+
const skipKeys = entries.filter((e) => e.kind === "header").map((e) => e.key);
|
|
31639
|
+
const result = await tuiSelect({
|
|
31640
|
+
items: entries,
|
|
31641
|
+
title: "Configuration",
|
|
31642
|
+
rl: ctx.rl,
|
|
31643
|
+
skipKeys,
|
|
31644
|
+
renderRow: renderConfigRow,
|
|
31645
|
+
onAction
|
|
31646
|
+
});
|
|
31647
|
+
if (result.confirmed && result.key) {
|
|
31648
|
+
const entry = entries.find((e) => e.key === result.key);
|
|
31649
|
+
if (entry?.kind === "action") {
|
|
31650
|
+
if (entry.value === "save_global") {
|
|
31651
|
+
applyConfigChanges(ctx, pendingChanges);
|
|
31652
|
+
ctx.saveSettings(pendingChanges);
|
|
31653
|
+
renderInfo("Settings saved globally.");
|
|
31654
|
+
hasChanges = false;
|
|
31655
|
+
return;
|
|
31656
|
+
}
|
|
31657
|
+
if (entry.value === "save_local") {
|
|
31658
|
+
applyConfigChanges(ctx, pendingChanges);
|
|
31659
|
+
ctx.saveLocalSettings(pendingChanges);
|
|
31660
|
+
renderInfo("Settings saved to project.");
|
|
31661
|
+
hasChanges = false;
|
|
31662
|
+
return;
|
|
31663
|
+
}
|
|
31664
|
+
}
|
|
31665
|
+
if (entry?.kind === "boolean" || entry?.kind === "enum") {
|
|
31666
|
+
onAction(entry, "right");
|
|
31667
|
+
applyConfigChanges(ctx, pendingChanges);
|
|
31668
|
+
ctx.saveSettings(pendingChanges);
|
|
31669
|
+
renderInfo(`${entry.key} set to ${c2.bold(entry.value)}`);
|
|
31670
|
+
return;
|
|
31671
|
+
}
|
|
31672
|
+
if (entry?.kind === "readonly") {
|
|
31673
|
+
renderInfo(`${entry.key} is read-only. Use the dedicated command (e.g. /model, /endpoint).`);
|
|
31674
|
+
return;
|
|
31675
|
+
}
|
|
31676
|
+
}
|
|
31677
|
+
if (hasChanges) {
|
|
31678
|
+
renderWarning("Unsaved config changes. Saving to global settings...");
|
|
31679
|
+
applyConfigChanges(ctx, pendingChanges);
|
|
31680
|
+
ctx.saveSettings(pendingChanges);
|
|
31681
|
+
renderInfo("Changes saved.");
|
|
31682
|
+
}
|
|
31683
|
+
}
|
|
31684
|
+
function applyConfigChanges(ctx, changes) {
|
|
31685
|
+
if (changes.verbose !== void 0)
|
|
31686
|
+
ctx.setVerbose(changes.verbose);
|
|
31687
|
+
if (changes.emojis !== void 0)
|
|
31688
|
+
ctx.setEmojis?.(changes.emojis);
|
|
31689
|
+
if (changes.colors !== void 0)
|
|
31690
|
+
ctx.setColors?.(changes.colors);
|
|
31691
|
+
if (changes.style !== void 0)
|
|
31692
|
+
ctx.setStyle?.(changes.style);
|
|
31693
|
+
if (changes.commandsMode !== void 0)
|
|
31694
|
+
ctx.setCommandsMode?.(changes.commandsMode);
|
|
31695
|
+
}
|
|
31367
31696
|
async function listModels(ctx) {
|
|
31368
31697
|
try {
|
|
31369
31698
|
const models = await fetchModels(ctx.config.backendUrl, ctx.config.apiKey);
|
|
@@ -31920,7 +32249,7 @@ var init_commands = __esm({
|
|
|
31920
32249
|
// packages/cli/dist/tui/project-context.js
|
|
31921
32250
|
import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
|
|
31922
32251
|
import { join as join40, basename as basename10 } from "node:path";
|
|
31923
|
-
import { execSync as
|
|
32252
|
+
import { execSync as execSync27 } from "node:child_process";
|
|
31924
32253
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
31925
32254
|
function getModelTier(modelName) {
|
|
31926
32255
|
const m = modelName.toLowerCase();
|
|
@@ -31966,19 +32295,19 @@ function loadProjectMap(repoRoot) {
|
|
|
31966
32295
|
}
|
|
31967
32296
|
function getGitInfo(repoRoot) {
|
|
31968
32297
|
try {
|
|
31969
|
-
|
|
32298
|
+
execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
31970
32299
|
} catch {
|
|
31971
32300
|
return "";
|
|
31972
32301
|
}
|
|
31973
32302
|
const lines = [];
|
|
31974
32303
|
try {
|
|
31975
|
-
const branch =
|
|
32304
|
+
const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
31976
32305
|
if (branch)
|
|
31977
32306
|
lines.push(`Branch: ${branch}`);
|
|
31978
32307
|
} catch {
|
|
31979
32308
|
}
|
|
31980
32309
|
try {
|
|
31981
|
-
const status =
|
|
32310
|
+
const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
31982
32311
|
if (status) {
|
|
31983
32312
|
const changed = status.split("\n").length;
|
|
31984
32313
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -31988,7 +32317,7 @@ function getGitInfo(repoRoot) {
|
|
|
31988
32317
|
} catch {
|
|
31989
32318
|
}
|
|
31990
32319
|
try {
|
|
31991
|
-
const log =
|
|
32320
|
+
const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
31992
32321
|
if (log)
|
|
31993
32322
|
lines.push(`Recent commits:
|
|
31994
32323
|
${log}`);
|
|
@@ -33405,7 +33734,7 @@ var init_carousel_descriptors = __esm({
|
|
|
33405
33734
|
import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
|
|
33406
33735
|
import { join as join42 } from "node:path";
|
|
33407
33736
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
33408
|
-
import { execSync as
|
|
33737
|
+
import { execSync as execSync28, spawn as nodeSpawn } from "node:child_process";
|
|
33409
33738
|
import { createRequire } from "node:module";
|
|
33410
33739
|
function voiceDir() {
|
|
33411
33740
|
return join42(homedir12(), ".open-agents", "voice");
|
|
@@ -34462,7 +34791,7 @@ var init_voice = __esm({
|
|
|
34462
34791
|
}
|
|
34463
34792
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
34464
34793
|
try {
|
|
34465
|
-
|
|
34794
|
+
execSync28(`which ${player}`, { stdio: "pipe" });
|
|
34466
34795
|
return [player, path];
|
|
34467
34796
|
} catch {
|
|
34468
34797
|
}
|
|
@@ -34491,7 +34820,7 @@ var init_voice = __esm({
|
|
|
34491
34820
|
return this.python3Path;
|
|
34492
34821
|
for (const bin of ["python3", "python"]) {
|
|
34493
34822
|
try {
|
|
34494
|
-
const path =
|
|
34823
|
+
const path = execSync28(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
34495
34824
|
if (path) {
|
|
34496
34825
|
this.python3Path = path;
|
|
34497
34826
|
return path;
|
|
@@ -34511,7 +34840,7 @@ var init_voice = __esm({
|
|
|
34511
34840
|
return false;
|
|
34512
34841
|
}
|
|
34513
34842
|
try {
|
|
34514
|
-
|
|
34843
|
+
execSync28(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
|
|
34515
34844
|
this.mlxInstalled = true;
|
|
34516
34845
|
return true;
|
|
34517
34846
|
} catch {
|
|
@@ -34535,7 +34864,7 @@ var init_voice = __esm({
|
|
|
34535
34864
|
return;
|
|
34536
34865
|
renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
|
|
34537
34866
|
try {
|
|
34538
|
-
|
|
34867
|
+
execSync28(`${py} -m pip install mlx-audio --quiet`, {
|
|
34539
34868
|
stdio: "pipe",
|
|
34540
34869
|
timeout: 3e5
|
|
34541
34870
|
// 5 min — may need to compile
|
|
@@ -34543,7 +34872,7 @@ var init_voice = __esm({
|
|
|
34543
34872
|
this.mlxInstalled = true;
|
|
34544
34873
|
} catch (err) {
|
|
34545
34874
|
try {
|
|
34546
|
-
|
|
34875
|
+
execSync28(`${py} -m pip install mlx-audio --user --quiet`, {
|
|
34547
34876
|
stdio: "pipe",
|
|
34548
34877
|
timeout: 3e5
|
|
34549
34878
|
});
|
|
@@ -34579,11 +34908,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34579
34908
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
34580
34909
|
].join("; ");
|
|
34581
34910
|
try {
|
|
34582
|
-
|
|
34911
|
+
execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34583
34912
|
} catch (err) {
|
|
34584
34913
|
try {
|
|
34585
34914
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
34586
|
-
|
|
34915
|
+
execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34587
34916
|
} catch (err2) {
|
|
34588
34917
|
return;
|
|
34589
34918
|
}
|
|
@@ -34647,11 +34976,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34647
34976
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
34648
34977
|
].join("; ");
|
|
34649
34978
|
try {
|
|
34650
|
-
|
|
34979
|
+
execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34651
34980
|
} catch {
|
|
34652
34981
|
try {
|
|
34653
34982
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
34654
|
-
|
|
34983
|
+
execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34655
34984
|
} catch {
|
|
34656
34985
|
return null;
|
|
34657
34986
|
}
|
|
@@ -34699,7 +35028,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34699
35028
|
const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
|
|
34700
35029
|
const probeOnnx = () => {
|
|
34701
35030
|
try {
|
|
34702
|
-
const result =
|
|
35031
|
+
const result = execSync28(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
|
|
34703
35032
|
const output = result.toString().trim();
|
|
34704
35033
|
return output === "OK";
|
|
34705
35034
|
} catch {
|
|
@@ -34716,7 +35045,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34716
35045
|
} catch {
|
|
34717
35046
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
34718
35047
|
try {
|
|
34719
|
-
|
|
35048
|
+
execSync28("npm install --no-audit --no-fund", {
|
|
34720
35049
|
cwd: voiceDir(),
|
|
34721
35050
|
stdio: "pipe",
|
|
34722
35051
|
timeout: 12e4
|
|
@@ -34741,7 +35070,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
34741
35070
|
} catch {
|
|
34742
35071
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
34743
35072
|
try {
|
|
34744
|
-
|
|
35073
|
+
execSync28("npm install --no-audit --no-fund", {
|
|
34745
35074
|
cwd: voiceDir(),
|
|
34746
35075
|
stdio: "pipe",
|
|
34747
35076
|
timeout: 12e4
|
|
@@ -35825,7 +36154,7 @@ var init_promptLoader3 = __esm({
|
|
|
35825
36154
|
// packages/cli/dist/tui/dream-engine.js
|
|
35826
36155
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
35827
36156
|
import { join as join45, basename as basename12 } from "node:path";
|
|
35828
|
-
import { execSync as
|
|
36157
|
+
import { execSync as execSync29 } from "node:child_process";
|
|
35829
36158
|
function loadAutoresearchMemory(repoRoot) {
|
|
35830
36159
|
const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
35831
36160
|
if (!existsSync34(memoryPath))
|
|
@@ -36189,7 +36518,7 @@ var init_dream_engine = __esm({
|
|
|
36189
36518
|
}
|
|
36190
36519
|
}
|
|
36191
36520
|
try {
|
|
36192
|
-
const output =
|
|
36521
|
+
const output = execSync29(cmd, {
|
|
36193
36522
|
cwd: this.repoRoot,
|
|
36194
36523
|
timeout: 3e4,
|
|
36195
36524
|
encoding: "utf-8",
|
|
@@ -36966,17 +37295,17 @@ ${summaryResult}
|
|
|
36966
37295
|
try {
|
|
36967
37296
|
mkdirSync14(checkpointDir, { recursive: true });
|
|
36968
37297
|
try {
|
|
36969
|
-
const gitStatus =
|
|
37298
|
+
const gitStatus = execSync29("git status --porcelain", {
|
|
36970
37299
|
cwd: this.repoRoot,
|
|
36971
37300
|
encoding: "utf-8",
|
|
36972
37301
|
timeout: 1e4
|
|
36973
37302
|
});
|
|
36974
|
-
const gitDiff =
|
|
37303
|
+
const gitDiff = execSync29("git diff", {
|
|
36975
37304
|
cwd: this.repoRoot,
|
|
36976
37305
|
encoding: "utf-8",
|
|
36977
37306
|
timeout: 1e4
|
|
36978
37307
|
});
|
|
36979
|
-
const gitHash =
|
|
37308
|
+
const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
36980
37309
|
cwd: this.repoRoot,
|
|
36981
37310
|
encoding: "utf-8",
|
|
36982
37311
|
timeout: 5e3
|
|
@@ -40830,6 +41159,62 @@ var init_status_bar = __esm({
|
|
|
40830
41159
|
if (this.active)
|
|
40831
41160
|
this.renderFooterPreserveCursor();
|
|
40832
41161
|
}
|
|
41162
|
+
/** Remote host metrics (when connected to a remote endpoint) */
|
|
41163
|
+
_remoteMetrics = null;
|
|
41164
|
+
_remoteMetricsTimer = null;
|
|
41165
|
+
/** Update remote host system metrics (from polling /v1/system/metrics) */
|
|
41166
|
+
setRemoteMetrics(metrics) {
|
|
41167
|
+
this._remoteMetrics = metrics;
|
|
41168
|
+
if (this.active)
|
|
41169
|
+
this.renderFooterPreserveCursor();
|
|
41170
|
+
}
|
|
41171
|
+
/** Clear remote metrics (e.g. when switching to local endpoint) */
|
|
41172
|
+
clearRemoteMetrics() {
|
|
41173
|
+
this._remoteMetrics = null;
|
|
41174
|
+
if (this._remoteMetricsTimer) {
|
|
41175
|
+
clearInterval(this._remoteMetricsTimer);
|
|
41176
|
+
this._remoteMetricsTimer = null;
|
|
41177
|
+
}
|
|
41178
|
+
if (this.active)
|
|
41179
|
+
this.renderFooterPreserveCursor();
|
|
41180
|
+
}
|
|
41181
|
+
/**
|
|
41182
|
+
* Start polling a remote endpoint for system metrics.
|
|
41183
|
+
* Call when /endpoint is set to a remote URL that has /v1/system/metrics.
|
|
41184
|
+
*/
|
|
41185
|
+
startRemoteMetricsPolling(endpointUrl, authKey) {
|
|
41186
|
+
this.stopRemoteMetricsPolling();
|
|
41187
|
+
const poll = async () => {
|
|
41188
|
+
try {
|
|
41189
|
+
const url = new URL("/v1/system/metrics", endpointUrl);
|
|
41190
|
+
const headers = {};
|
|
41191
|
+
if (authKey)
|
|
41192
|
+
headers["Authorization"] = `Bearer ${authKey}`;
|
|
41193
|
+
const resp = await fetch(url.toString(), { headers, signal: AbortSignal.timeout(5e3) });
|
|
41194
|
+
if (resp.ok) {
|
|
41195
|
+
const data = await resp.json();
|
|
41196
|
+
this.setRemoteMetrics({
|
|
41197
|
+
cpuUtil: data.cpu?.utilization ?? 0,
|
|
41198
|
+
gpuUtil: data.gpu?.available ? data.gpu.utilization ?? 0 : -1,
|
|
41199
|
+
gpuName: data.gpu?.name ?? "",
|
|
41200
|
+
vramUtil: data.gpu?.available ? data.gpu.vramUtilization ?? 0 : -1,
|
|
41201
|
+
memUtil: data.memory?.utilization ?? 0
|
|
41202
|
+
});
|
|
41203
|
+
}
|
|
41204
|
+
} catch {
|
|
41205
|
+
}
|
|
41206
|
+
};
|
|
41207
|
+
poll();
|
|
41208
|
+
this._remoteMetricsTimer = setInterval(poll, 1e4);
|
|
41209
|
+
}
|
|
41210
|
+
/** Stop polling remote metrics */
|
|
41211
|
+
stopRemoteMetricsPolling() {
|
|
41212
|
+
if (this._remoteMetricsTimer) {
|
|
41213
|
+
clearInterval(this._remoteMetricsTimer);
|
|
41214
|
+
this._remoteMetricsTimer = null;
|
|
41215
|
+
}
|
|
41216
|
+
this._remoteMetrics = null;
|
|
41217
|
+
}
|
|
40833
41218
|
/** Update token metrics from a token_usage event */
|
|
40834
41219
|
updateMetrics(update) {
|
|
40835
41220
|
if (update.promptTokens !== void 0)
|
|
@@ -41193,6 +41578,35 @@ var init_status_bar = __esm({
|
|
|
41193
41578
|
empty: false
|
|
41194
41579
|
});
|
|
41195
41580
|
}
|
|
41581
|
+
if (this._remoteMetrics) {
|
|
41582
|
+
const rm2 = this._remoteMetrics;
|
|
41583
|
+
const cpuColor = rm2.cpuUtil > 80 ? c2.red : rm2.cpuUtil > 50 ? c2.yellow : c2.green;
|
|
41584
|
+
const cpuStr = `CPU:${cpuColor(rm2.cpuUtil + "%")}`;
|
|
41585
|
+
const cpuW = 4 + `${rm2.cpuUtil}%`.length;
|
|
41586
|
+
let gpuStr = "";
|
|
41587
|
+
let gpuW = 0;
|
|
41588
|
+
if (rm2.gpuUtil >= 0) {
|
|
41589
|
+
const gpuColor = rm2.gpuUtil > 80 ? c2.red : rm2.gpuUtil > 50 ? c2.yellow : c2.green;
|
|
41590
|
+
gpuStr = ` GPU:${gpuColor(rm2.gpuUtil + "%")}`;
|
|
41591
|
+
gpuW = 5 + `${rm2.gpuUtil}%`.length;
|
|
41592
|
+
}
|
|
41593
|
+
let vramStr = "";
|
|
41594
|
+
let vramW = 0;
|
|
41595
|
+
if (rm2.vramUtil >= 0) {
|
|
41596
|
+
const vramColor = rm2.vramUtil > 80 ? c2.red : rm2.vramUtil > 50 ? c2.yellow : c2.green;
|
|
41597
|
+
vramStr = ` VRAM:${vramColor(rm2.vramUtil + "%")}`;
|
|
41598
|
+
vramW = 6 + `${rm2.vramUtil}%`.length;
|
|
41599
|
+
}
|
|
41600
|
+
const remoteExpanded = pastel2(117, "\u{1F4E1}") + " " + cpuStr + gpuStr + vramStr;
|
|
41601
|
+
const remoteCompact = pastel2(117, "\u{1F4E1}") + " " + cpuStr + gpuStr;
|
|
41602
|
+
sections.push({
|
|
41603
|
+
expanded: remoteExpanded,
|
|
41604
|
+
compact: remoteCompact,
|
|
41605
|
+
expandedW: 3 + cpuW + gpuW + vramW,
|
|
41606
|
+
compactW: 3 + cpuW + gpuW,
|
|
41607
|
+
empty: false
|
|
41608
|
+
});
|
|
41609
|
+
}
|
|
41196
41610
|
if (this._recording) {
|
|
41197
41611
|
const dot = this._recBlink ? pastel2(210, "\u25CF") : " ";
|
|
41198
41612
|
const countdown = this._countdown > 0 ? c2.dim(` ${this._countdown}s`) : "";
|
|
@@ -42888,6 +43302,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
42888
43302
|
};
|
|
42889
43303
|
const newProvider = detectProvider(url);
|
|
42890
43304
|
costTracker.setProvider(newProvider.id);
|
|
43305
|
+
const isRemote = !url.includes("127.0.0.1") && !url.includes("localhost");
|
|
43306
|
+
if (isRemote) {
|
|
43307
|
+
statusBar.startRemoteMetricsPolling(url, apiKey);
|
|
43308
|
+
} else {
|
|
43309
|
+
statusBar.stopRemoteMetricsPolling();
|
|
43310
|
+
}
|
|
42891
43311
|
},
|
|
42892
43312
|
clearScreen() {
|
|
42893
43313
|
process.stdout.write("\x1B[2J\x1B[H");
|
package/package.json
CHANGED