open-agents-ai 0.103.8 → 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 +399 -111
- 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
|
});
|
|
@@ -30250,7 +30305,8 @@ function tuiSelect(opts) {
|
|
|
30250
30305
|
lines.push(` ${selectColors.dim(` \u25BC ${remaining} more`)}`);
|
|
30251
30306
|
}
|
|
30252
30307
|
lines.push("");
|
|
30253
|
-
|
|
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")}`);
|
|
30254
30310
|
lines.push("");
|
|
30255
30311
|
const output = lines.join("\n");
|
|
30256
30312
|
process.stdout.write(output);
|
|
@@ -30320,6 +30376,21 @@ function tuiSelect(opts) {
|
|
|
30320
30376
|
cursor = last;
|
|
30321
30377
|
render();
|
|
30322
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
|
+
}
|
|
30323
30394
|
} else if (seq === "\r" || seq === "\n") {
|
|
30324
30395
|
if (!isSkippable(cursor) && matchSet.has(cursor)) {
|
|
30325
30396
|
cleanup();
|
|
@@ -30426,38 +30497,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
30426
30497
|
return "handled";
|
|
30427
30498
|
case "config":
|
|
30428
30499
|
case "cfg": {
|
|
30429
|
-
|
|
30430
|
-
const globalS = loadGlobalSettings();
|
|
30431
|
-
const merged = { ...globalS, ...resolved };
|
|
30432
|
-
renderConfig({
|
|
30433
|
-
// -- Core inference --
|
|
30434
|
-
model: ctx.config.model,
|
|
30435
|
-
backendType: ctx.config.backendType,
|
|
30436
|
-
backendUrl: ctx.config.backendUrl,
|
|
30437
|
-
apiKey: ctx.config.apiKey ? "[set]" : "[not set]",
|
|
30438
|
-
maxRetries: String(ctx.config.maxRetries),
|
|
30439
|
-
timeoutMs: String(ctx.config.timeoutMs),
|
|
30440
|
-
dbPath: ctx.config.dbPath,
|
|
30441
|
-
// -- Behaviour --
|
|
30442
|
-
dryRun: String(ctx.config.dryRun),
|
|
30443
|
-
verbose: String(ctx.config.verbose),
|
|
30444
|
-
stream: String(merged.stream ?? false),
|
|
30445
|
-
bruteforce: String(merged.bruteforce ?? false),
|
|
30446
|
-
deepContext: String(merged.deepContext ?? false),
|
|
30447
|
-
// -- Presentation --
|
|
30448
|
-
emojis: String(ctx.getEmojis?.() ?? merged.emojis ?? true),
|
|
30449
|
-
colors: String(ctx.getColors?.() ?? merged.colors ?? true),
|
|
30450
|
-
style: String(ctx.getStyle?.() ?? merged.style ?? "balanced"),
|
|
30451
|
-
// -- Voice --
|
|
30452
|
-
voice: String(merged.voice ?? false),
|
|
30453
|
-
voiceModel: String(merged.voiceModel ?? "glados"),
|
|
30454
|
-
// -- Autonomy --
|
|
30455
|
-
commandsMode: String(ctx.getCommandsMode?.() ?? merged.commandsMode ?? "manual"),
|
|
30456
|
-
updateMode: String(merged.updateMode ?? "auto"),
|
|
30457
|
-
// -- Integrations --
|
|
30458
|
-
telegramKey: merged.telegramKey ? "[set]" : "[not set]",
|
|
30459
|
-
telegramAdmin: String(merged.telegramAdmin ?? "[not set]")
|
|
30460
|
-
});
|
|
30500
|
+
await showConfigEditor(ctx);
|
|
30461
30501
|
return "handled";
|
|
30462
30502
|
}
|
|
30463
30503
|
case "cost":
|
|
@@ -30871,25 +30911,26 @@ async function handleSlashCommand(input, ctx) {
|
|
|
30871
30911
|
}
|
|
30872
30912
|
case "commands":
|
|
30873
30913
|
case "cmds": {
|
|
30874
|
-
if (!ctx.getCommandsMode || !ctx.setCommandsMode) {
|
|
30875
|
-
renderWarning("Commands mode not available in this context.");
|
|
30876
|
-
return "handled";
|
|
30877
|
-
}
|
|
30878
30914
|
if (arg === "auto") {
|
|
30915
|
+
if (!ctx.setCommandsMode) {
|
|
30916
|
+
renderWarning("Commands mode not available.");
|
|
30917
|
+
return "handled";
|
|
30918
|
+
}
|
|
30879
30919
|
ctx.setCommandsMode("auto");
|
|
30880
30920
|
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30881
30921
|
save({ commandsMode: "auto" });
|
|
30882
30922
|
renderInfo("Commands mode: auto \u2014 the agent can now invoke slash commands as tools.");
|
|
30883
30923
|
} else if (arg === "manual") {
|
|
30924
|
+
if (!ctx.setCommandsMode) {
|
|
30925
|
+
renderWarning("Commands mode not available.");
|
|
30926
|
+
return "handled";
|
|
30927
|
+
}
|
|
30884
30928
|
ctx.setCommandsMode("manual");
|
|
30885
30929
|
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30886
30930
|
save({ commandsMode: "manual" });
|
|
30887
30931
|
renderInfo("Commands mode: manual \u2014 slash commands are user-only.");
|
|
30888
30932
|
} else {
|
|
30889
|
-
|
|
30890
|
-
renderInfo(`Commands mode: ${c2.bold(current)}`);
|
|
30891
|
-
renderInfo(" /commands auto \u2014 agent can invoke slash commands as tools");
|
|
30892
|
-
renderInfo(" /commands manual \u2014 slash commands are user-only (default)");
|
|
30933
|
+
renderSlashHelp();
|
|
30893
30934
|
}
|
|
30894
30935
|
return "handled";
|
|
30895
30936
|
}
|
|
@@ -31496,6 +31537,162 @@ async function handleSlashCommand(input, ctx) {
|
|
|
31496
31537
|
}
|
|
31497
31538
|
}
|
|
31498
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
|
+
}
|
|
31499
31696
|
async function listModels(ctx) {
|
|
31500
31697
|
try {
|
|
31501
31698
|
const models = await fetchModels(ctx.config.backendUrl, ctx.config.apiKey);
|
|
@@ -32052,7 +32249,7 @@ var init_commands = __esm({
|
|
|
32052
32249
|
// packages/cli/dist/tui/project-context.js
|
|
32053
32250
|
import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
|
|
32054
32251
|
import { join as join40, basename as basename10 } from "node:path";
|
|
32055
|
-
import { execSync as
|
|
32252
|
+
import { execSync as execSync27 } from "node:child_process";
|
|
32056
32253
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
32057
32254
|
function getModelTier(modelName) {
|
|
32058
32255
|
const m = modelName.toLowerCase();
|
|
@@ -32098,19 +32295,19 @@ function loadProjectMap(repoRoot) {
|
|
|
32098
32295
|
}
|
|
32099
32296
|
function getGitInfo(repoRoot) {
|
|
32100
32297
|
try {
|
|
32101
|
-
|
|
32298
|
+
execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
32102
32299
|
} catch {
|
|
32103
32300
|
return "";
|
|
32104
32301
|
}
|
|
32105
32302
|
const lines = [];
|
|
32106
32303
|
try {
|
|
32107
|
-
const branch =
|
|
32304
|
+
const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
32108
32305
|
if (branch)
|
|
32109
32306
|
lines.push(`Branch: ${branch}`);
|
|
32110
32307
|
} catch {
|
|
32111
32308
|
}
|
|
32112
32309
|
try {
|
|
32113
|
-
const status =
|
|
32310
|
+
const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
32114
32311
|
if (status) {
|
|
32115
32312
|
const changed = status.split("\n").length;
|
|
32116
32313
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -32120,7 +32317,7 @@ function getGitInfo(repoRoot) {
|
|
|
32120
32317
|
} catch {
|
|
32121
32318
|
}
|
|
32122
32319
|
try {
|
|
32123
|
-
const log =
|
|
32320
|
+
const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
32124
32321
|
if (log)
|
|
32125
32322
|
lines.push(`Recent commits:
|
|
32126
32323
|
${log}`);
|
|
@@ -33537,7 +33734,7 @@ var init_carousel_descriptors = __esm({
|
|
|
33537
33734
|
import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
|
|
33538
33735
|
import { join as join42 } from "node:path";
|
|
33539
33736
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
33540
|
-
import { execSync as
|
|
33737
|
+
import { execSync as execSync28, spawn as nodeSpawn } from "node:child_process";
|
|
33541
33738
|
import { createRequire } from "node:module";
|
|
33542
33739
|
function voiceDir() {
|
|
33543
33740
|
return join42(homedir12(), ".open-agents", "voice");
|
|
@@ -34594,7 +34791,7 @@ var init_voice = __esm({
|
|
|
34594
34791
|
}
|
|
34595
34792
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
34596
34793
|
try {
|
|
34597
|
-
|
|
34794
|
+
execSync28(`which ${player}`, { stdio: "pipe" });
|
|
34598
34795
|
return [player, path];
|
|
34599
34796
|
} catch {
|
|
34600
34797
|
}
|
|
@@ -34623,7 +34820,7 @@ var init_voice = __esm({
|
|
|
34623
34820
|
return this.python3Path;
|
|
34624
34821
|
for (const bin of ["python3", "python"]) {
|
|
34625
34822
|
try {
|
|
34626
|
-
const path =
|
|
34823
|
+
const path = execSync28(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
34627
34824
|
if (path) {
|
|
34628
34825
|
this.python3Path = path;
|
|
34629
34826
|
return path;
|
|
@@ -34643,7 +34840,7 @@ var init_voice = __esm({
|
|
|
34643
34840
|
return false;
|
|
34644
34841
|
}
|
|
34645
34842
|
try {
|
|
34646
|
-
|
|
34843
|
+
execSync28(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
|
|
34647
34844
|
this.mlxInstalled = true;
|
|
34648
34845
|
return true;
|
|
34649
34846
|
} catch {
|
|
@@ -34667,7 +34864,7 @@ var init_voice = __esm({
|
|
|
34667
34864
|
return;
|
|
34668
34865
|
renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
|
|
34669
34866
|
try {
|
|
34670
|
-
|
|
34867
|
+
execSync28(`${py} -m pip install mlx-audio --quiet`, {
|
|
34671
34868
|
stdio: "pipe",
|
|
34672
34869
|
timeout: 3e5
|
|
34673
34870
|
// 5 min — may need to compile
|
|
@@ -34675,7 +34872,7 @@ var init_voice = __esm({
|
|
|
34675
34872
|
this.mlxInstalled = true;
|
|
34676
34873
|
} catch (err) {
|
|
34677
34874
|
try {
|
|
34678
|
-
|
|
34875
|
+
execSync28(`${py} -m pip install mlx-audio --user --quiet`, {
|
|
34679
34876
|
stdio: "pipe",
|
|
34680
34877
|
timeout: 3e5
|
|
34681
34878
|
});
|
|
@@ -34711,11 +34908,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34711
34908
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
34712
34909
|
].join("; ");
|
|
34713
34910
|
try {
|
|
34714
|
-
|
|
34911
|
+
execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34715
34912
|
} catch (err) {
|
|
34716
34913
|
try {
|
|
34717
34914
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
34718
|
-
|
|
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() });
|
|
34719
34916
|
} catch (err2) {
|
|
34720
34917
|
return;
|
|
34721
34918
|
}
|
|
@@ -34779,11 +34976,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34779
34976
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
34780
34977
|
].join("; ");
|
|
34781
34978
|
try {
|
|
34782
|
-
|
|
34979
|
+
execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
|
|
34783
34980
|
} catch {
|
|
34784
34981
|
try {
|
|
34785
34982
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
34786
|
-
|
|
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() });
|
|
34787
34984
|
} catch {
|
|
34788
34985
|
return null;
|
|
34789
34986
|
}
|
|
@@ -34831,7 +35028,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34831
35028
|
const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
|
|
34832
35029
|
const probeOnnx = () => {
|
|
34833
35030
|
try {
|
|
34834
|
-
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") } });
|
|
34835
35032
|
const output = result.toString().trim();
|
|
34836
35033
|
return output === "OK";
|
|
34837
35034
|
} catch {
|
|
@@ -34848,7 +35045,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
34848
35045
|
} catch {
|
|
34849
35046
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
34850
35047
|
try {
|
|
34851
|
-
|
|
35048
|
+
execSync28("npm install --no-audit --no-fund", {
|
|
34852
35049
|
cwd: voiceDir(),
|
|
34853
35050
|
stdio: "pipe",
|
|
34854
35051
|
timeout: 12e4
|
|
@@ -34873,7 +35070,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
34873
35070
|
} catch {
|
|
34874
35071
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
34875
35072
|
try {
|
|
34876
|
-
|
|
35073
|
+
execSync28("npm install --no-audit --no-fund", {
|
|
34877
35074
|
cwd: voiceDir(),
|
|
34878
35075
|
stdio: "pipe",
|
|
34879
35076
|
timeout: 12e4
|
|
@@ -35957,7 +36154,7 @@ var init_promptLoader3 = __esm({
|
|
|
35957
36154
|
// packages/cli/dist/tui/dream-engine.js
|
|
35958
36155
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
35959
36156
|
import { join as join45, basename as basename12 } from "node:path";
|
|
35960
|
-
import { execSync as
|
|
36157
|
+
import { execSync as execSync29 } from "node:child_process";
|
|
35961
36158
|
function loadAutoresearchMemory(repoRoot) {
|
|
35962
36159
|
const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
35963
36160
|
if (!existsSync34(memoryPath))
|
|
@@ -36321,7 +36518,7 @@ var init_dream_engine = __esm({
|
|
|
36321
36518
|
}
|
|
36322
36519
|
}
|
|
36323
36520
|
try {
|
|
36324
|
-
const output =
|
|
36521
|
+
const output = execSync29(cmd, {
|
|
36325
36522
|
cwd: this.repoRoot,
|
|
36326
36523
|
timeout: 3e4,
|
|
36327
36524
|
encoding: "utf-8",
|
|
@@ -37098,17 +37295,17 @@ ${summaryResult}
|
|
|
37098
37295
|
try {
|
|
37099
37296
|
mkdirSync14(checkpointDir, { recursive: true });
|
|
37100
37297
|
try {
|
|
37101
|
-
const gitStatus =
|
|
37298
|
+
const gitStatus = execSync29("git status --porcelain", {
|
|
37102
37299
|
cwd: this.repoRoot,
|
|
37103
37300
|
encoding: "utf-8",
|
|
37104
37301
|
timeout: 1e4
|
|
37105
37302
|
});
|
|
37106
|
-
const gitDiff =
|
|
37303
|
+
const gitDiff = execSync29("git diff", {
|
|
37107
37304
|
cwd: this.repoRoot,
|
|
37108
37305
|
encoding: "utf-8",
|
|
37109
37306
|
timeout: 1e4
|
|
37110
37307
|
});
|
|
37111
|
-
const gitHash =
|
|
37308
|
+
const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
37112
37309
|
cwd: this.repoRoot,
|
|
37113
37310
|
encoding: "utf-8",
|
|
37114
37311
|
timeout: 5e3
|
|
@@ -40962,6 +41159,62 @@ var init_status_bar = __esm({
|
|
|
40962
41159
|
if (this.active)
|
|
40963
41160
|
this.renderFooterPreserveCursor();
|
|
40964
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
|
+
}
|
|
40965
41218
|
/** Update token metrics from a token_usage event */
|
|
40966
41219
|
updateMetrics(update) {
|
|
40967
41220
|
if (update.promptTokens !== void 0)
|
|
@@ -41325,6 +41578,35 @@ var init_status_bar = __esm({
|
|
|
41325
41578
|
empty: false
|
|
41326
41579
|
});
|
|
41327
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
|
+
}
|
|
41328
41610
|
if (this._recording) {
|
|
41329
41611
|
const dot = this._recBlink ? pastel2(210, "\u25CF") : " ";
|
|
41330
41612
|
const countdown = this._countdown > 0 ? c2.dim(` ${this._countdown}s`) : "";
|
|
@@ -43020,6 +43302,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
43020
43302
|
};
|
|
43021
43303
|
const newProvider = detectProvider(url);
|
|
43022
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
|
+
}
|
|
43023
43311
|
},
|
|
43024
43312
|
clearScreen() {
|
|
43025
43313
|
process.stdout.write("\x1B[2J\x1B[H");
|
package/package.json
CHANGED