open-agents-ai 0.187.215 → 0.187.217
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 +242 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -293277,6 +293277,7 @@ __export(setup_exports, {
|
|
|
293277
293277
|
pullModelWithAutoUpdate: () => pullModelWithAutoUpdate,
|
|
293278
293278
|
recommendModel: () => recommendModel,
|
|
293279
293279
|
renderScoreBar: () => renderScoreBar,
|
|
293280
|
+
runElevatedCommand: () => runElevatedCommand,
|
|
293280
293281
|
runSetupWizard: () => runSetupWizard,
|
|
293281
293282
|
updateOllama: () => updateOllama
|
|
293282
293283
|
});
|
|
@@ -293564,15 +293565,24 @@ function ensureZstd() {
|
|
|
293564
293565
|
process.stdout.write(`
|
|
293565
293566
|
${c3.cyan("●")} Installing zstd (required by ollama install.sh)...
|
|
293566
293567
|
`);
|
|
293567
|
-
const
|
|
293568
|
-
|
|
293569
|
-
|
|
293570
|
-
|
|
293571
|
-
|
|
293572
|
-
|
|
293573
|
-
|
|
293568
|
+
const hasDisplay = !!(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
293569
|
+
const askpassHelper = detectAskpassHelper() ?? writeAskpassHelper();
|
|
293570
|
+
const askpassEnv = askpassHelper ? { ...process.env, SUDO_ASKPASS: askpassHelper, DEBIAN_FRONTEND: "noninteractive" } : { ...process.env, DEBIAN_FRONTEND: "noninteractive" };
|
|
293571
|
+
const candidates = [];
|
|
293572
|
+
if (hasCmd("pkexec") && hasDisplay) {
|
|
293573
|
+
candidates.push({ cmd: `pkexec sh -c ${shellEscape(installCmd)}`, env: process.env });
|
|
293574
|
+
}
|
|
293575
|
+
if (askpassHelper) {
|
|
293576
|
+
candidates.push({ cmd: `sudo -A ${installCmd}`, env: askpassEnv });
|
|
293577
|
+
}
|
|
293578
|
+
candidates.push({ cmd: installCmd, env: process.env });
|
|
293579
|
+
for (const cand of candidates) {
|
|
293574
293580
|
try {
|
|
293575
|
-
execSync48(cmd, {
|
|
293581
|
+
execSync48(cand.cmd, {
|
|
293582
|
+
stdio: ["ignore", "inherit", "pipe"],
|
|
293583
|
+
env: cand.env,
|
|
293584
|
+
timeout: 18e4
|
|
293585
|
+
});
|
|
293576
293586
|
if (hasCmd("zstd")) {
|
|
293577
293587
|
process.stdout.write(` ${c3.green("✔")} zstd installed.
|
|
293578
293588
|
`);
|
|
@@ -293585,17 +293595,159 @@ function ensureZstd() {
|
|
|
293585
293595
|
`);
|
|
293586
293596
|
return false;
|
|
293587
293597
|
}
|
|
293598
|
+
function detectAskpassHelper() {
|
|
293599
|
+
const linuxHelpers = [
|
|
293600
|
+
"/usr/lib/ssh/ssh-askpass",
|
|
293601
|
+
// openssh-askpass
|
|
293602
|
+
"/usr/lib/openssh/ssh-askpass",
|
|
293603
|
+
"/usr/libexec/openssh/ssh-askpass",
|
|
293604
|
+
"/usr/bin/ksshaskpass",
|
|
293605
|
+
// KDE
|
|
293606
|
+
"/usr/bin/lxqt-openssh-askpass"
|
|
293607
|
+
];
|
|
293608
|
+
if (process.platform === "linux") {
|
|
293609
|
+
for (const path5 of linuxHelpers) {
|
|
293610
|
+
try {
|
|
293611
|
+
if (existsSync59(path5)) return path5;
|
|
293612
|
+
} catch {
|
|
293613
|
+
}
|
|
293614
|
+
}
|
|
293615
|
+
for (const name10 of ["ssh-askpass", "ksshaskpass", "x11-ssh-askpass"]) {
|
|
293616
|
+
if (hasCmd(name10)) {
|
|
293617
|
+
try {
|
|
293618
|
+
const p2 = execSync48(`command -v ${name10}`, { encoding: "utf8" }).trim();
|
|
293619
|
+
if (p2) return p2;
|
|
293620
|
+
} catch {
|
|
293621
|
+
}
|
|
293622
|
+
}
|
|
293623
|
+
}
|
|
293624
|
+
}
|
|
293625
|
+
return null;
|
|
293626
|
+
}
|
|
293627
|
+
function writeAskpassHelper() {
|
|
293628
|
+
const tmpDir = join76(homedir26(), ".open-agents");
|
|
293629
|
+
try {
|
|
293630
|
+
mkdirSync33(tmpDir, { recursive: true });
|
|
293631
|
+
} catch {
|
|
293632
|
+
}
|
|
293633
|
+
const helperPath = join76(tmpDir, "askpass-helper.sh");
|
|
293634
|
+
let body = "";
|
|
293635
|
+
if (process.platform === "darwin") {
|
|
293636
|
+
body = `#!/bin/sh
|
|
293637
|
+
osascript -e 'Tell application "System Events" to display dialog "Open Agents needs admin access to update Ollama.\\n\\nPassword:" with title "Open Agents" with hidden answer default answer "" buttons {"Cancel","OK"} default button "OK"' -e 'text returned of result' 2>/dev/null
|
|
293638
|
+
`;
|
|
293639
|
+
} else if (process.platform === "linux") {
|
|
293640
|
+
const hasZenity = hasCmd("zenity");
|
|
293641
|
+
const hasKdialog = hasCmd("kdialog");
|
|
293642
|
+
const hasYad = hasCmd("yad");
|
|
293643
|
+
if (!hasZenity && !hasKdialog && !hasYad) return null;
|
|
293644
|
+
const lines = ["#!/bin/sh", 'TITLE="Open Agents"', 'TEXT="Open Agents needs admin access to update Ollama. Enter your password:"'];
|
|
293645
|
+
if (hasZenity) {
|
|
293646
|
+
lines.push('zenity --password --title="$TITLE" --text="$TEXT" 2>/dev/null && exit 0');
|
|
293647
|
+
}
|
|
293648
|
+
if (hasKdialog) {
|
|
293649
|
+
lines.push('kdialog --title "$TITLE" --password "$TEXT" 2>/dev/null && exit 0');
|
|
293650
|
+
}
|
|
293651
|
+
if (hasYad) {
|
|
293652
|
+
lines.push('yad --title="$TITLE" --text="$TEXT" --entry --hide-text 2>/dev/null && exit 0');
|
|
293653
|
+
}
|
|
293654
|
+
lines.push("exit 1");
|
|
293655
|
+
body = lines.join("\n") + "\n";
|
|
293656
|
+
} else {
|
|
293657
|
+
return null;
|
|
293658
|
+
}
|
|
293659
|
+
try {
|
|
293660
|
+
writeFileSync30(helperPath, body, { mode: 448 });
|
|
293661
|
+
execSync48(`chmod 700 "${helperPath}"`, { stdio: "ignore" });
|
|
293662
|
+
return helperPath;
|
|
293663
|
+
} catch {
|
|
293664
|
+
return null;
|
|
293665
|
+
}
|
|
293666
|
+
}
|
|
293667
|
+
function buildElevatedInstall() {
|
|
293668
|
+
const installCmd = "curl -fsSL https://ollama.com/install.sh | sh";
|
|
293669
|
+
const baseEnv = { ...process.env };
|
|
293670
|
+
if (process.platform === "linux" && hasCmd("pkexec") && (process.env.DISPLAY || process.env.WAYLAND_DISPLAY)) {
|
|
293671
|
+
return {
|
|
293672
|
+
cmd: `pkexec sh -c ${shellEscape(installCmd)}`,
|
|
293673
|
+
env: baseEnv,
|
|
293674
|
+
mode: "pkexec"
|
|
293675
|
+
};
|
|
293676
|
+
}
|
|
293677
|
+
const nativeAskpass = detectAskpassHelper();
|
|
293678
|
+
const writtenHelper = nativeAskpass ?? writeAskpassHelper();
|
|
293679
|
+
if (writtenHelper) {
|
|
293680
|
+
return {
|
|
293681
|
+
cmd: installCmd,
|
|
293682
|
+
// unchanged — install.sh's internal sudo calls will use ASKPASS
|
|
293683
|
+
env: { ...baseEnv, SUDO_ASKPASS: writtenHelper, DEBIAN_FRONTEND: "noninteractive" },
|
|
293684
|
+
mode: "askpass"
|
|
293685
|
+
};
|
|
293686
|
+
}
|
|
293687
|
+
return {
|
|
293688
|
+
cmd: installCmd,
|
|
293689
|
+
env: baseEnv,
|
|
293690
|
+
mode: "fallback"
|
|
293691
|
+
};
|
|
293692
|
+
}
|
|
293693
|
+
function shellEscape(s2) {
|
|
293694
|
+
return `'${s2.replace(/'/g, `'\\''`)}'`;
|
|
293695
|
+
}
|
|
293696
|
+
function runElevatedCommand(command, opts = {}) {
|
|
293697
|
+
const timeout2 = opts.timeoutMs ?? 6e4;
|
|
293698
|
+
const hasDisplay = !!(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
293699
|
+
const askpassHelper = detectAskpassHelper() ?? writeAskpassHelper();
|
|
293700
|
+
const askpassEnv = askpassHelper ? { ...process.env, SUDO_ASKPASS: askpassHelper } : process.env;
|
|
293701
|
+
const candidates = [];
|
|
293702
|
+
if (hasCmd("pkexec") && hasDisplay) {
|
|
293703
|
+
candidates.push({ cmd: `pkexec sh -c ${shellEscape(command)}`, env: process.env });
|
|
293704
|
+
}
|
|
293705
|
+
if (askpassHelper) {
|
|
293706
|
+
candidates.push({ cmd: `sudo -A sh -c ${shellEscape(command)}`, env: askpassEnv });
|
|
293707
|
+
}
|
|
293708
|
+
candidates.push({ cmd: command, env: process.env });
|
|
293709
|
+
let lastErr = null;
|
|
293710
|
+
for (const cand of candidates) {
|
|
293711
|
+
try {
|
|
293712
|
+
execSync48(cand.cmd, {
|
|
293713
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
293714
|
+
// never inherit TUI stdin
|
|
293715
|
+
env: cand.env,
|
|
293716
|
+
timeout: timeout2
|
|
293717
|
+
});
|
|
293718
|
+
return;
|
|
293719
|
+
} catch (err) {
|
|
293720
|
+
lastErr = err;
|
|
293721
|
+
}
|
|
293722
|
+
}
|
|
293723
|
+
if (!opts.swallowErrors && lastErr) {
|
|
293724
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
293725
|
+
}
|
|
293726
|
+
}
|
|
293588
293727
|
function runOllamaInstallScript() {
|
|
293589
293728
|
const zstdReady = ensureZstd();
|
|
293590
293729
|
if (!zstdReady) {
|
|
293591
293730
|
process.stdout.write(` ${c3.yellow("⚠")} Proceeding without zstd — install may fail if the script requires it.
|
|
293592
293731
|
`);
|
|
293593
293732
|
}
|
|
293594
|
-
const
|
|
293733
|
+
const elevated = buildElevatedInstall();
|
|
293734
|
+
if (elevated.mode === "pkexec") {
|
|
293735
|
+
process.stdout.write(` ${c3.cyan("●")} Elevation: pkexec (graphical PolicyKit prompt)
|
|
293736
|
+
`);
|
|
293737
|
+
} else if (elevated.mode === "askpass") {
|
|
293738
|
+
process.stdout.write(` ${c3.cyan("●")} Elevation: SUDO_ASKPASS (GUI password modal)
|
|
293739
|
+
`);
|
|
293740
|
+
} else {
|
|
293741
|
+
process.stdout.write(` ${c3.yellow("⚠")} No GUI password helper available — install may stall waiting for sudo.
|
|
293742
|
+
`);
|
|
293743
|
+
process.stdout.write(` ${c3.yellow("⚠")} Install one of: pkexec / zenity / kdialog / yad / ssh-askpass
|
|
293744
|
+
`);
|
|
293745
|
+
}
|
|
293595
293746
|
const runOnce = () => {
|
|
293596
|
-
execSync48(cmd, {
|
|
293597
|
-
stdio: ["
|
|
293598
|
-
|
|
293747
|
+
execSync48(elevated.cmd, {
|
|
293748
|
+
stdio: ["ignore", "inherit", "pipe"],
|
|
293749
|
+
env: elevated.env,
|
|
293750
|
+
timeout: 6e5
|
|
293599
293751
|
});
|
|
293600
293752
|
};
|
|
293601
293753
|
try {
|
|
@@ -304975,10 +305127,13 @@ async function handleParallel(arg, ctx3) {
|
|
|
304975
305127
|
const overrideContent = `[Service]
|
|
304976
305128
|
Environment="OLLAMA_NUM_PARALLEL=${n2}"
|
|
304977
305129
|
`;
|
|
304978
|
-
|
|
304979
|
-
|
|
304980
|
-
|
|
304981
|
-
|
|
305130
|
+
const { runElevatedCommand: runElev } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
305131
|
+
runElev(`mkdir -p ${overrideDir}`, { timeoutMs: 3e4 });
|
|
305132
|
+
const escapedContent = overrideContent.replace(/'/g, `'\\''`);
|
|
305133
|
+
runElev(`bash -c 'cat > ${overrideFile} <<EOF
|
|
305134
|
+
${escapedContent}EOF'`, { timeoutMs: 3e4 });
|
|
305135
|
+
runElev("systemctl daemon-reload", { timeoutMs: 3e4 });
|
|
305136
|
+
runElev("systemctl restart ollama.service", { timeoutMs: 3e4 });
|
|
304982
305137
|
let ready = false;
|
|
304983
305138
|
for (let i2 = 0; i2 < 30 && !ready; i2++) {
|
|
304984
305139
|
await new Promise((r2) => setTimeout(r2, 500));
|
|
@@ -305410,8 +305565,8 @@ async function handleUpdate(subcommand, ctx3) {
|
|
|
305410
305565
|
if (doUpdateOllama()) {
|
|
305411
305566
|
renderInfo("Ollama updated successfully.");
|
|
305412
305567
|
try {
|
|
305413
|
-
const {
|
|
305414
|
-
|
|
305568
|
+
const { runElevatedCommand: runElevatedCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
305569
|
+
runElevatedCommand2("systemctl restart ollama", { timeoutMs: 1e4, swallowErrors: true });
|
|
305415
305570
|
} catch {
|
|
305416
305571
|
}
|
|
305417
305572
|
} else {
|
|
@@ -316896,17 +317051,16 @@ body {
|
|
|
316896
317051
|
|
|
316897
317052
|
/* WO-TASK-02 — task progress strip (shares processes-row styling) */
|
|
316898
317053
|
#tasks-row {
|
|
316899
|
-
display: none; /* hidden until tasks exist */
|
|
317054
|
+
display: none; /* hidden until tasks exist; flipped to flex when populated */
|
|
317055
|
+
flex-flow: row wrap; /* wrap items onto multiple lines for long lists */
|
|
316900
317056
|
align-items: center;
|
|
316901
|
-
gap: 6px;
|
|
317057
|
+
gap: 6px 6px; /* row gap + column gap once wrapping kicks in */
|
|
316902
317058
|
padding: 4px 16px;
|
|
316903
317059
|
min-height: 22px;
|
|
316904
317060
|
background: #17171a;
|
|
316905
317061
|
border-bottom: 1px solid #2a2a30;
|
|
316906
|
-
|
|
316907
|
-
scrollbar-width: none;
|
|
317062
|
+
/* Wrap instead of horizontal scroll so all tasks are visible */
|
|
316908
317063
|
}
|
|
316909
|
-
#tasks-row::-webkit-scrollbar { display: none; }
|
|
316910
317064
|
#tasks-row .tasks-label {
|
|
316911
317065
|
color: #444;
|
|
316912
317066
|
font-size: 0.55rem;
|
|
@@ -317707,17 +317861,75 @@ async function sendMessage() {
|
|
|
317707
317861
|
details.style.cssText = 'background:#1e1e22;border-left:2px solid #b2920a;margin:2px 0;font-size:0.7rem';
|
|
317708
317862
|
const summary = document.createElement('summary');
|
|
317709
317863
|
summary.style.cssText = 'padding:4px 8px;color:#b2920a;cursor:pointer';
|
|
317710
|
-
|
|
317864
|
+
|
|
317865
|
+
// Build a compact one-line label so the user sees what the tool
|
|
317866
|
+
// is actually doing without expanding. todo_write gets a special
|
|
317867
|
+
// status-counter summary; everything else gets a short args
|
|
317868
|
+
// preview that JSON-stringifies arrays/objects so they don't
|
|
317869
|
+
// render as "[object Object],[object Object],...".
|
|
317870
|
+
const toolName = chunk.tool || 'tool';
|
|
317871
|
+
const a = (chunk.args && typeof chunk.args === 'object') ? chunk.args : {};
|
|
317872
|
+
let inlineSummary = '';
|
|
317873
|
+
if (toolName === 'todo_write' && Array.isArray(a.todos)) {
|
|
317874
|
+
const todos = a.todos;
|
|
317875
|
+
let p = 0, ip = 0, c = 0, b = 0;
|
|
317876
|
+
for (const t of todos) {
|
|
317877
|
+
const s = (t && typeof t === 'object') ? t.status : '';
|
|
317878
|
+
if (s === 'completed') c++;
|
|
317879
|
+
else if (s === 'in_progress') ip++;
|
|
317880
|
+
else if (s === 'blocked') b++;
|
|
317881
|
+
else p++;
|
|
317882
|
+
}
|
|
317883
|
+
inlineSummary = ' — ' + todos.length + ' items (' + c + '◉ ' + ip + '◐ ' + p + '〇' + (b > 0 ? ' ' + b + '◍' : '') + ')';
|
|
317884
|
+
} else {
|
|
317885
|
+
const previewParts = [];
|
|
317886
|
+
for (const [k, v] of Object.entries(a)) {
|
|
317887
|
+
let vs;
|
|
317888
|
+
if (v === null || v === undefined) vs = String(v);
|
|
317889
|
+
else if (typeof v === 'string') vs = v;
|
|
317890
|
+
else if (typeof v === 'number' || typeof v === 'boolean') vs = String(v);
|
|
317891
|
+
else { try { vs = JSON.stringify(v); } catch { vs = '[object]'; } }
|
|
317892
|
+
if (vs.length > 60) vs = vs.slice(0, 57) + '…';
|
|
317893
|
+
previewParts.push(k + '=' + vs);
|
|
317894
|
+
if (previewParts.length >= 3) break;
|
|
317895
|
+
}
|
|
317896
|
+
if (previewParts.length) inlineSummary = ' — ' + previewParts.join(', ');
|
|
317897
|
+
}
|
|
317898
|
+
summary.textContent = '▸ ' + toolName + inlineSummary;
|
|
317711
317899
|
details.appendChild(summary);
|
|
317712
|
-
|
|
317900
|
+
|
|
317901
|
+
// Expandable args — unpack all key-value pairs. CRITICAL: stringify
|
|
317902
|
+
// arrays/objects so they don't show as "[object Object]". For
|
|
317903
|
+
// todo_write specifically render a checklist instead of a blob.
|
|
317713
317904
|
if (chunk.args && typeof chunk.args === 'object') {
|
|
317714
317905
|
const argsDiv = document.createElement('div');
|
|
317715
317906
|
argsDiv.style.cssText = 'padding:4px 8px 6px 16px;color:#888;font-size:0.65rem;border-top:1px solid #2a2a30';
|
|
317716
|
-
|
|
317717
|
-
const
|
|
317718
|
-
|
|
317719
|
-
|
|
317720
|
-
|
|
317907
|
+
if (toolName === 'todo_write' && Array.isArray(a.todos)) {
|
|
317908
|
+
for (const t of a.todos) {
|
|
317909
|
+
if (!t || typeof t !== 'object') continue;
|
|
317910
|
+
const row = document.createElement('div');
|
|
317911
|
+
row.style.cssText = 'padding:2px 0';
|
|
317912
|
+
let mark = '〇';
|
|
317913
|
+
let color = '#666';
|
|
317914
|
+
if (t.status === 'completed') { mark = '◉'; color = '#4a7a4a'; }
|
|
317915
|
+
else if (t.status === 'in_progress') { mark = '◐'; color = '#b2920a'; }
|
|
317916
|
+
else if (t.status === 'blocked') { mark = '◍'; color = '#b25f5f'; }
|
|
317917
|
+
row.innerHTML = '<span style="color:' + color + '">' + mark + '</span> <span style="color:#b0b0b0">' + escHtml(String(t.content || '').slice(0, 300)) + '</span>' + (t.blocker ? ' <span style="color:#b25f5f">(blocked: ' + escHtml(String(t.blocker).slice(0, 100)) + ')</span>' : '');
|
|
317918
|
+
argsDiv.appendChild(row);
|
|
317919
|
+
}
|
|
317920
|
+
} else {
|
|
317921
|
+
for (const [k, v] of Object.entries(chunk.args)) {
|
|
317922
|
+
const row = document.createElement('div');
|
|
317923
|
+
row.style.cssText = 'padding:2px 0;display:flex;gap:8px';
|
|
317924
|
+
let vs;
|
|
317925
|
+
if (v === null || v === undefined) vs = String(v);
|
|
317926
|
+
else if (typeof v === 'string') vs = v;
|
|
317927
|
+
else if (typeof v === 'number' || typeof v === 'boolean') vs = String(v);
|
|
317928
|
+
else { try { vs = JSON.stringify(v, null, 2); } catch { vs = '[object]'; } }
|
|
317929
|
+
if (vs.length > 500) vs = vs.slice(0, 497) + '…';
|
|
317930
|
+
row.innerHTML = '<span style="color:#b2920a;min-width:60px">' + k + '</span><span style="color:#b0b0b0;word-break:break-all;white-space:pre-wrap">' + escHtml(vs) + '</span>';
|
|
317931
|
+
argsDiv.appendChild(row);
|
|
317932
|
+
}
|
|
317721
317933
|
}
|
|
317722
317934
|
details.appendChild(argsDiv);
|
|
317723
317935
|
}
|
package/package.json
CHANGED