open-agents-ai 0.187.365 → 0.187.367
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 +210 -79
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -539097,6 +539097,7 @@ var init_neovim_mode = __esm({
|
|
|
539097
539097
|
var daemon_exports = {};
|
|
539098
539098
|
__export(daemon_exports, {
|
|
539099
539099
|
ensureDaemon: () => ensureDaemon,
|
|
539100
|
+
forceKillDaemon: () => forceKillDaemon,
|
|
539100
539101
|
getDaemonPid: () => getDaemonPid,
|
|
539101
539102
|
getDaemonStatus: () => getDaemonStatus,
|
|
539102
539103
|
isDaemonRunning: () => isDaemonRunning,
|
|
@@ -539200,6 +539201,67 @@ function stopDaemon() {
|
|
|
539200
539201
|
return false;
|
|
539201
539202
|
}
|
|
539202
539203
|
}
|
|
539204
|
+
async function forceKillDaemon(port) {
|
|
539205
|
+
const p2 = port ?? getDaemonPort();
|
|
539206
|
+
let killed = 0;
|
|
539207
|
+
const pid = getDaemonPid();
|
|
539208
|
+
if (pid) {
|
|
539209
|
+
try {
|
|
539210
|
+
process.kill(pid, "SIGTERM");
|
|
539211
|
+
killed++;
|
|
539212
|
+
} catch {
|
|
539213
|
+
}
|
|
539214
|
+
for (let i2 = 0; i2 < 20; i2++) {
|
|
539215
|
+
await new Promise((r2) => setTimeout(r2, 100));
|
|
539216
|
+
try {
|
|
539217
|
+
process.kill(pid, 0);
|
|
539218
|
+
} catch {
|
|
539219
|
+
break;
|
|
539220
|
+
}
|
|
539221
|
+
}
|
|
539222
|
+
try {
|
|
539223
|
+
process.kill(pid, 0);
|
|
539224
|
+
process.kill(pid, "SIGKILL");
|
|
539225
|
+
killed++;
|
|
539226
|
+
} catch {
|
|
539227
|
+
}
|
|
539228
|
+
try {
|
|
539229
|
+
unlinkSync16(PID_FILE2);
|
|
539230
|
+
} catch {
|
|
539231
|
+
}
|
|
539232
|
+
}
|
|
539233
|
+
try {
|
|
539234
|
+
const { execSync: execSync57 } = await import("node:child_process");
|
|
539235
|
+
const out = execSync57(
|
|
539236
|
+
`lsof -ti :${p2} 2>/dev/null || fuser ${p2}/tcp 2>/dev/null || true`,
|
|
539237
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
539238
|
+
).trim();
|
|
539239
|
+
const pids = out.split(/[\s\n]+/).map((s2) => parseInt(s2, 10)).filter((n2) => Number.isFinite(n2) && n2 > 0 && n2 !== process.pid);
|
|
539240
|
+
for (const otherPid of pids) {
|
|
539241
|
+
try {
|
|
539242
|
+
process.kill(otherPid, "SIGTERM");
|
|
539243
|
+
killed++;
|
|
539244
|
+
} catch {
|
|
539245
|
+
}
|
|
539246
|
+
}
|
|
539247
|
+
if (pids.length > 0) {
|
|
539248
|
+
await new Promise((r2) => setTimeout(r2, 1e3));
|
|
539249
|
+
for (const otherPid of pids) {
|
|
539250
|
+
try {
|
|
539251
|
+
process.kill(otherPid, 0);
|
|
539252
|
+
process.kill(otherPid, "SIGKILL");
|
|
539253
|
+
} catch {
|
|
539254
|
+
}
|
|
539255
|
+
}
|
|
539256
|
+
}
|
|
539257
|
+
} catch {
|
|
539258
|
+
}
|
|
539259
|
+
for (let i2 = 0; i2 < 50; i2++) {
|
|
539260
|
+
if (!await isDaemonRunning(p2)) return killed;
|
|
539261
|
+
await new Promise((r2) => setTimeout(r2, 100));
|
|
539262
|
+
}
|
|
539263
|
+
return killed;
|
|
539264
|
+
}
|
|
539203
539265
|
async function ensureDaemon() {
|
|
539204
539266
|
const port = getDaemonPort();
|
|
539205
539267
|
if (await isDaemonRunning(port)) {
|
|
@@ -544447,12 +544509,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
544447
544509
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
544448
544510
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
544449
544511
|
try {
|
|
544450
|
-
const { homedir:
|
|
544451
|
-
const { mkdirSync:
|
|
544452
|
-
const { join:
|
|
544453
|
-
const dir =
|
|
544454
|
-
|
|
544455
|
-
|
|
544512
|
+
const { homedir: homedir42 } = await import("node:os");
|
|
544513
|
+
const { mkdirSync: mkdirSync59, writeFileSync: writeFileSync52 } = await import("node:fs");
|
|
544514
|
+
const { join: join111 } = await import("node:path");
|
|
544515
|
+
const dir = join111(homedir42(), ".open-agents");
|
|
544516
|
+
mkdirSync59(dir, { recursive: true });
|
|
544517
|
+
writeFileSync52(join111(dir, "api.key"), apiKey + "\n", "utf8");
|
|
544456
544518
|
} catch {
|
|
544457
544519
|
}
|
|
544458
544520
|
}
|
|
@@ -544462,29 +544524,66 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
544462
544524
|
ctx4.saveSettings({ oaAccess: val2 });
|
|
544463
544525
|
}
|
|
544464
544526
|
const port2 = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
544465
|
-
let switched2 = false;
|
|
544466
544527
|
try {
|
|
544467
|
-
const
|
|
544528
|
+
const { homedir: homedir42 } = await import("node:os");
|
|
544529
|
+
const { mkdirSync: mkdirSync59, writeFileSync: writeFileSync52 } = await import("node:fs");
|
|
544530
|
+
const { join: join111 } = await import("node:path");
|
|
544531
|
+
const dir = join111(homedir42(), ".open-agents");
|
|
544532
|
+
mkdirSync59(dir, { recursive: true });
|
|
544533
|
+
writeFileSync52(join111(dir, "access"), `${val2}
|
|
544534
|
+
`, "utf8");
|
|
544535
|
+
} catch {
|
|
544536
|
+
}
|
|
544537
|
+
const baseUrl2 = `http://127.0.0.1:${port2}`;
|
|
544538
|
+
const authHeaders2 = () => {
|
|
544539
|
+
const token = process.env["OA_API_KEY"] || "";
|
|
544540
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
544541
|
+
};
|
|
544542
|
+
let liveOk2 = false;
|
|
544543
|
+
try {
|
|
544544
|
+
const resp = await fetch(`${baseUrl2}/v1/admin/access`, {
|
|
544468
544545
|
method: "POST",
|
|
544469
|
-
headers: { "Content-Type": "application/json" },
|
|
544546
|
+
headers: { "Content-Type": "application/json", ...authHeaders2() },
|
|
544470
544547
|
body: JSON.stringify({ mode: val2 }),
|
|
544471
544548
|
signal: AbortSignal.timeout(3e3)
|
|
544472
544549
|
});
|
|
544473
|
-
|
|
544550
|
+
liveOk2 = resp.ok;
|
|
544474
544551
|
} catch {
|
|
544475
544552
|
}
|
|
544476
|
-
|
|
544553
|
+
const readCurrent2 = async () => {
|
|
544554
|
+
try {
|
|
544555
|
+
const r2 = await fetch(`${baseUrl2}/v1/admin/access`, { headers: authHeaders2(), signal: AbortSignal.timeout(2e3) });
|
|
544556
|
+
if (!r2.ok) return null;
|
|
544557
|
+
const j = await r2.json();
|
|
544558
|
+
return typeof j.mode === "string" ? j.mode : null;
|
|
544559
|
+
} catch {
|
|
544560
|
+
return null;
|
|
544561
|
+
}
|
|
544562
|
+
};
|
|
544563
|
+
const current2 = await readCurrent2();
|
|
544564
|
+
if (liveOk2 && current2 === val2) {
|
|
544477
544565
|
renderInfo2(`Access policy now '${val2}' (live, no restart). Persisted to ~/.open-agents/access.`);
|
|
544566
|
+
return "handled";
|
|
544567
|
+
}
|
|
544568
|
+
renderInfo2(`Live switch did not take effect (daemon reports ${current2 ?? "unreachable"}). Force-restarting...`);
|
|
544569
|
+
const { forceKillDaemon: forceKillDaemon3, ensureDaemon: ensureDaemon3 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
|
|
544570
|
+
const killed2 = await forceKillDaemon3(port2);
|
|
544571
|
+
if (killed2 > 0) renderInfo2(`Force-killed ${killed2} process(es) bound to port ${port2}.`);
|
|
544572
|
+
const ok3 = await ensureDaemon3();
|
|
544573
|
+
if (!ok3) {
|
|
544574
|
+
renderError2("Failed to start a fresh daemon after force-kill.");
|
|
544575
|
+
return "handled";
|
|
544576
|
+
}
|
|
544577
|
+
let finalMode2 = null;
|
|
544578
|
+
for (let i2 = 0; i2 < 10; i2++) {
|
|
544579
|
+
finalMode2 = await readCurrent2();
|
|
544580
|
+
if (finalMode2) break;
|
|
544581
|
+
await new Promise((r2) => setTimeout(r2, 250));
|
|
544582
|
+
}
|
|
544583
|
+
if (finalMode2 === val2) {
|
|
544584
|
+
renderInfo2(`Access policy now '${val2}' (daemon restarted, verified).`);
|
|
544478
544585
|
} else {
|
|
544479
|
-
|
|
544480
|
-
stopDaemon2();
|
|
544481
|
-
const deadline = Date.now() + 4e3;
|
|
544482
|
-
while (Date.now() < deadline) {
|
|
544483
|
-
if (!await isDaemonRunning2(port2)) break;
|
|
544484
|
-
await new Promise((r2) => setTimeout(r2, 200));
|
|
544485
|
-
}
|
|
544486
|
-
const ok2 = await ensureDaemon2();
|
|
544487
|
-
renderInfo2(ok2 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
|
|
544586
|
+
renderWarning2(`Daemon restarted but reports mode='${finalMode2 ?? "unreachable"}'. Expected '${val2}'.`);
|
|
544488
544587
|
}
|
|
544489
544588
|
return "handled";
|
|
544490
544589
|
}
|
|
@@ -544512,12 +544611,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
544512
544611
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
544513
544612
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
544514
544613
|
try {
|
|
544515
|
-
const { homedir:
|
|
544516
|
-
const { mkdirSync:
|
|
544517
|
-
const { join:
|
|
544518
|
-
const dir =
|
|
544519
|
-
|
|
544520
|
-
|
|
544614
|
+
const { homedir: homedir42 } = await import("node:os");
|
|
544615
|
+
const { mkdirSync: mkdirSync59, writeFileSync: writeFileSync52 } = await import("node:fs");
|
|
544616
|
+
const { join: join111 } = await import("node:path");
|
|
544617
|
+
const dir = join111(homedir42(), ".open-agents");
|
|
544618
|
+
mkdirSync59(dir, { recursive: true });
|
|
544619
|
+
writeFileSync52(join111(dir, "api.key"), apiKey + "\n", "utf8");
|
|
544521
544620
|
} catch {
|
|
544522
544621
|
}
|
|
544523
544622
|
}
|
|
@@ -544527,34 +544626,72 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
544527
544626
|
ctx3.saveSettings({ oaAccess: val });
|
|
544528
544627
|
}
|
|
544529
544628
|
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
544530
|
-
|
|
544629
|
+
const { homedir: homedir41 } = await import("node:os");
|
|
544630
|
+
const { mkdirSync: mkdirSync58, writeFileSync: writeFileSync51 } = await import("node:fs");
|
|
544631
|
+
const { join: join110 } = await import("node:path");
|
|
544531
544632
|
try {
|
|
544532
|
-
const
|
|
544633
|
+
const dir = join110(homedir41(), ".open-agents");
|
|
544634
|
+
mkdirSync58(dir, { recursive: true });
|
|
544635
|
+
writeFileSync51(join110(dir, "access"), `${val}
|
|
544636
|
+
`, "utf8");
|
|
544637
|
+
} catch (e2) {
|
|
544638
|
+
renderWarning2(`Could not persist ~/.open-agents/access: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
544639
|
+
}
|
|
544640
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
544641
|
+
const authHeaders = () => {
|
|
544642
|
+
const token = process.env["OA_API_KEY"] || "";
|
|
544643
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
544644
|
+
};
|
|
544645
|
+
let liveOk = false;
|
|
544646
|
+
try {
|
|
544647
|
+
const resp = await fetch(`${baseUrl}/v1/admin/access`, {
|
|
544533
544648
|
method: "POST",
|
|
544534
|
-
headers: { "Content-Type": "application/json" },
|
|
544649
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
544535
544650
|
body: JSON.stringify({ mode: val }),
|
|
544536
544651
|
signal: AbortSignal.timeout(3e3)
|
|
544537
544652
|
});
|
|
544538
|
-
|
|
544653
|
+
liveOk = resp.ok;
|
|
544539
544654
|
if (!resp.ok) {
|
|
544540
544655
|
const txt = await resp.text().catch(() => "");
|
|
544541
544656
|
renderWarning2(`Live access switch HTTP ${resp.status}: ${txt.slice(0, 120)}`);
|
|
544542
544657
|
}
|
|
544543
544658
|
} catch (e2) {
|
|
544544
|
-
renderWarning2(`Live access switch failed
|
|
544659
|
+
renderWarning2(`Live access switch fetch failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
544545
544660
|
}
|
|
544546
|
-
|
|
544661
|
+
const readCurrent = async () => {
|
|
544662
|
+
try {
|
|
544663
|
+
const r2 = await fetch(`${baseUrl}/v1/admin/access`, { headers: authHeaders(), signal: AbortSignal.timeout(2e3) });
|
|
544664
|
+
if (!r2.ok) return null;
|
|
544665
|
+
const j = await r2.json();
|
|
544666
|
+
return typeof j.mode === "string" ? j.mode : null;
|
|
544667
|
+
} catch {
|
|
544668
|
+
return null;
|
|
544669
|
+
}
|
|
544670
|
+
};
|
|
544671
|
+
let current = await readCurrent();
|
|
544672
|
+
if (liveOk && current === val) {
|
|
544547
544673
|
renderInfo2(`Access policy now '${val}' (live, no restart). Persisted to ~/.open-agents/access.`);
|
|
544674
|
+
return "handled";
|
|
544675
|
+
}
|
|
544676
|
+
renderInfo2(`Live switch did not take effect (daemon reports ${current ?? "unreachable"}). Force-restarting daemon...`);
|
|
544677
|
+
const { forceKillDaemon: forceKillDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
|
|
544678
|
+
const killed = await forceKillDaemon2(port);
|
|
544679
|
+
if (killed > 0) renderInfo2(`Force-killed ${killed} process(es) bound to port ${port}.`);
|
|
544680
|
+
const ok2 = await ensureDaemon2();
|
|
544681
|
+
if (!ok2) {
|
|
544682
|
+
renderError2("Failed to start a fresh daemon after force-kill. Try: `oa serve --quiet --daemon &` manually.");
|
|
544683
|
+
return "handled";
|
|
544684
|
+
}
|
|
544685
|
+
let finalMode = null;
|
|
544686
|
+
for (let i2 = 0; i2 < 10; i2++) {
|
|
544687
|
+
finalMode = await readCurrent();
|
|
544688
|
+
if (finalMode) break;
|
|
544689
|
+
await new Promise((r2) => setTimeout(r2, 250));
|
|
544690
|
+
}
|
|
544691
|
+
if (finalMode === val) {
|
|
544692
|
+
renderInfo2(`Access policy now '${val}' (daemon restarted, verified via /v1/admin/access).`);
|
|
544548
544693
|
} else {
|
|
544549
|
-
|
|
544550
|
-
stopDaemon2();
|
|
544551
|
-
const deadline = Date.now() + 4e3;
|
|
544552
|
-
while (Date.now() < deadline) {
|
|
544553
|
-
if (!await isDaemonRunning2(port)) break;
|
|
544554
|
-
await new Promise((r2) => setTimeout(r2, 200));
|
|
544555
|
-
}
|
|
544556
|
-
const ok2 = await ensureDaemon2();
|
|
544557
|
-
renderInfo2(ok2 ? "Daemon restarted to apply access policy." : "Failed to restart daemon.");
|
|
544694
|
+
renderWarning2(`Daemon restarted but reports mode='${finalMode ?? "unreachable"}'. Expected '${val}'. Check ~/.open-agents/access.`);
|
|
544558
544695
|
}
|
|
544559
544696
|
return "handled";
|
|
544560
544697
|
}
|
|
@@ -569010,12 +569147,12 @@ async function loadScheduled() {
|
|
|
569010
569147
|
const rows = tasks.map(t => {
|
|
569011
569148
|
const enabled = !!t.enabled;
|
|
569012
569149
|
const btn = enabled
|
|
569013
|
-
? '<button onclick="toggleScheduled('' + t.id + '',false)" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">disable</button>'
|
|
569014
|
-
: '<button onclick="toggleScheduled('' + t.id + '',true)" style="background:#2a2a30;border:1px solid #2a3a2a;color:#4ec94e;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">enable</button>';
|
|
569150
|
+
? '<button onclick="toggleScheduled(\\'' + t.id + '\\',false)" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">disable</button>'
|
|
569151
|
+
: '<button onclick="toggleScheduled(\\'' + t.id + '\\',true)" style="background:#2a2a30;border:1px solid #2a3a2a;color:#4ec94e;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">enable</button>';
|
|
569015
569152
|
const color = enabled ? '#4ec94e' : '#5a2a2a';
|
|
569016
569153
|
const procInfo = t.procs && t.procs.length ? (' (' + t.procs.length + ' proc)') : '';
|
|
569017
569154
|
const up = t.procs && t.procs[0] && t.procs[0].uptime_s ? (' • up ' + Math.max(1, Math.round(t.procs[0].uptime_s/60)) + 'm') : '';
|
|
569018
|
-
const killBtn = '<button onclick="killScheduledTask('' + t.id + '')" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">kill</button>';
|
|
569155
|
+
const killBtn = '<button onclick="killScheduledTask(\\'' + t.id + '\\')" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">kill</button>';
|
|
569019
569156
|
const row = '<div style="background:#1e1e22;border-left:2px solid ' + color + ';padding:6px 10px;margin:4px 0;font-size:0.72rem">'
|
|
569020
569157
|
+ '<div style="color:#b0b0b0">' + (t.name || '(task)') + ' <span style="color:#555">' + (t.schedule || '') + '</span>' + procInfo + up + '</div>'
|
|
569021
569158
|
+ '<div style="color:#555;font-size:0.6rem">' + t.file + '#' + t.index + '</div>'
|
|
@@ -569035,14 +569172,14 @@ async function loadScheduled() {
|
|
|
569035
569172
|
} catch {}
|
|
569036
569173
|
}
|
|
569037
569174
|
|
|
569038
|
-
|
|
569175
|
+
window.toggleScheduled = async function(id, enabled) {
|
|
569039
569176
|
try {
|
|
569040
569177
|
await fetch('/v1/scheduled/' + encodeURIComponent(id), { method:'POST', headers: headers(), body: JSON.stringify({enabled}) });
|
|
569041
569178
|
loadScheduled();
|
|
569042
569179
|
} catch {}
|
|
569043
569180
|
}
|
|
569044
569181
|
|
|
569045
|
-
|
|
569182
|
+
window.killScheduled = async function() {
|
|
569046
569183
|
try {
|
|
569047
569184
|
const r = await fetch('/v1/scheduled/kill', { method:'POST', headers: headers(), body: JSON.stringify({}) });
|
|
569048
569185
|
const j = await r.json();
|
|
@@ -569053,18 +569190,15 @@ async function loadScheduled() {
|
|
|
569053
569190
|
const rem = Array.isArray(j.procs_after) ? j.procs_after.length : 0;
|
|
569054
569191
|
let msg = 'Killed ' + (kb + ka) + ' processes.';
|
|
569055
569192
|
if (before && after) {
|
|
569056
|
-
msg += '
|
|
569057
|
-
GPU util: ' + before.gpu_pct + '% → ' + after.gpu_pct + '%, VRAM: ' + before.vram_used_gb + '/' + before.vram_total_gb + ' GB → ' + after.vram_used_gb + '/' + after.vram_total_gb + ' GB';
|
|
569193
|
+
msg += '\\nGPU util: ' + before.gpu_pct + '% → ' + after.gpu_pct + '%, VRAM: ' + before.vram_used_gb + '/' + before.vram_total_gb + ' GB → ' + after.vram_used_gb + '/' + after.vram_total_gb + ' GB';
|
|
569058
569194
|
}
|
|
569059
|
-
msg += rem > 0 ? ('
|
|
569060
|
-
Remaining matched processes: ' + rem) : '
|
|
569061
|
-
No remaining matched processes.';
|
|
569195
|
+
msg += rem > 0 ? ('\\nRemaining matched processes: ' + rem) : '\\nNo remaining matched processes.';
|
|
569062
569196
|
alert(msg);
|
|
569063
569197
|
loadScheduled();
|
|
569064
569198
|
} catch (e) { alert('Kill failed: ' + (e && e.message || String(e))); }
|
|
569065
569199
|
}
|
|
569066
569200
|
|
|
569067
|
-
|
|
569201
|
+
window.disableAllScheduled = async function() {
|
|
569068
569202
|
try {
|
|
569069
569203
|
const r = await fetch('/v1/scheduled', { headers: headers() });
|
|
569070
569204
|
const d = await r.json();
|
|
@@ -569081,7 +569215,7 @@ No remaining matched processes.';
|
|
|
569081
569215
|
} catch {}
|
|
569082
569216
|
}
|
|
569083
569217
|
|
|
569084
|
-
|
|
569218
|
+
window.enableAllScheduled = async function() {
|
|
569085
569219
|
try {
|
|
569086
569220
|
const r = await fetch('/v1/scheduled', { headers: headers() });
|
|
569087
569221
|
const d = await r.json();
|
|
@@ -569098,7 +569232,7 @@ No remaining matched processes.';
|
|
|
569098
569232
|
} catch {}
|
|
569099
569233
|
}
|
|
569100
569234
|
|
|
569101
|
-
|
|
569235
|
+
window.adoptScheduled = async function() {
|
|
569102
569236
|
try {
|
|
569103
569237
|
const r = await fetch('/v1/scheduled/reconcile', { method:'POST', headers: headers(), body: JSON.stringify({ apply: true }) });
|
|
569104
569238
|
const j = await r.json();
|
|
@@ -569110,7 +569244,7 @@ No remaining matched processes.';
|
|
|
569110
569244
|
} catch (e) { alert('Adopt failed: ' + (e && e.message || String(e))); }
|
|
569111
569245
|
}
|
|
569112
569246
|
|
|
569113
|
-
|
|
569247
|
+
window.fixupScheduled = async function() {
|
|
569114
569248
|
try {
|
|
569115
569249
|
if (!confirm('Rewrite OA cron entries to canonical launcher?')) return;
|
|
569116
569250
|
const r = await fetch('/v1/scheduled/fixup', { method:'POST', headers: headers(), body: JSON.stringify({ mode: 'cron', dryRun: false }) });
|
|
@@ -569120,7 +569254,7 @@ No remaining matched processes.';
|
|
|
569120
569254
|
} catch (e) { alert('Fixup failed: ' + (e && e.message || String(e))); }
|
|
569121
569255
|
}
|
|
569122
569256
|
|
|
569123
|
-
|
|
569257
|
+
window.migrateScheduled = async function() {
|
|
569124
569258
|
try {
|
|
569125
569259
|
if (!confirm('Migrate OA cron entries to systemd user timers?')) return;
|
|
569126
569260
|
const r = await fetch('/v1/scheduled/fixup', { method:'POST', headers: headers(), body: JSON.stringify({ mode: 'migrate', dryRun: false }) });
|
|
@@ -569130,7 +569264,7 @@ No remaining matched processes.';
|
|
|
569130
569264
|
} catch (e) { alert('Migrate failed: ' + (e && e.message || String(e))); }
|
|
569131
569265
|
}
|
|
569132
569266
|
|
|
569133
|
-
|
|
569267
|
+
window.killScheduledTask = async function(id) {
|
|
569134
569268
|
try {
|
|
569135
569269
|
// Fetch task to derive a pattern (directory of tasks.json)
|
|
569136
569270
|
const r = await fetch('/v1/scheduled/status', { headers: headers() });
|
|
@@ -569141,20 +569275,20 @@ No remaining matched processes.';
|
|
|
569141
569275
|
const dir = (t.file || '').split('/').slice(0, -1).join('/') || t.file;
|
|
569142
569276
|
// Escape for regex without using a character class that includes brace/dollar combo (parser quirk)
|
|
569143
569277
|
const safe = dir
|
|
569144
|
-
.replace(
|
|
569145
|
-
.replace(
|
|
569146
|
-
.replace(
|
|
569147
|
-
.replace(
|
|
569148
|
-
.replace(
|
|
569149
|
-
.replace(
|
|
569150
|
-
.replace(
|
|
569151
|
-
.replace(
|
|
569152
|
-
.replace(
|
|
569153
|
-
.replace(
|
|
569154
|
-
.replace(
|
|
569155
|
-
.replace(
|
|
569156
|
-
.replace(
|
|
569157
|
-
.replace(
|
|
569278
|
+
.replace(/\\\\/g, "\\\\\\\\")
|
|
569279
|
+
.replace(/\\[/g, "\\\\[")
|
|
569280
|
+
.replace(/\\]/g, "\\\\]")
|
|
569281
|
+
.replace(/\\{/g, "\\\\{")
|
|
569282
|
+
.replace(/\\}/g, "\\\\}")
|
|
569283
|
+
.replace(/\\(/g, "\\\\(")
|
|
569284
|
+
.replace(/\\)/g, "\\\\)")
|
|
569285
|
+
.replace(/\\*/g, "\\\\*")
|
|
569286
|
+
.replace(/\\+/g, "\\\\+")
|
|
569287
|
+
.replace(/\\?/g, "\\\\?")
|
|
569288
|
+
.replace(/\\^/g, "\\\\^")
|
|
569289
|
+
.replace(/\\$/g, "\\\\$")
|
|
569290
|
+
.replace(/\\|/g, "\\\\|")
|
|
569291
|
+
.replace(/\\./g, "\\\\.");
|
|
569158
569292
|
const body = { pattern: safe };
|
|
569159
569293
|
const resp = await fetch('/v1/scheduled/kill', { method:'POST', headers: headers(), body: JSON.stringify(body) });
|
|
569160
569294
|
const j = await resp.json();
|
|
@@ -569164,11 +569298,8 @@ No remaining matched processes.';
|
|
|
569164
569298
|
const after = j.gpu_after && j.gpu_after[0] ? j.gpu_after[0] : null;
|
|
569165
569299
|
const rem = Array.isArray(j.procs_after) ? j.procs_after.length : 0;
|
|
569166
569300
|
let msg = 'Killed ' + (kb + ka) + ' processes for task.';
|
|
569167
|
-
if (before && after) msg += '
|
|
569168
|
-
|
|
569169
|
-
msg += rem > 0 ? ('
|
|
569170
|
-
Remaining matched processes: ' + rem) : '
|
|
569171
|
-
No remaining matched processes.';
|
|
569301
|
+
if (before && after) msg += '\\nGPU util: ' + before.gpu_pct + '% → ' + after.gpu_pct + '%';
|
|
569302
|
+
msg += rem > 0 ? ('\\nRemaining matched processes: ' + rem) : '\\nNo remaining matched processes.';
|
|
569172
569303
|
alert(msg);
|
|
569173
569304
|
loadScheduled();
|
|
569174
569305
|
} catch (e) { alert('Kill failed: ' + (e && e.message || String(e))); }
|
|
@@ -569183,8 +569314,8 @@ async function loadServices() {
|
|
|
569183
569314
|
const svcs = Array.isArray(d.services) ? d.services : [];
|
|
569184
569315
|
if (!svcs.length) { el.innerHTML = ''; return; }
|
|
569185
569316
|
const rows = svcs.map(s => {
|
|
569186
|
-
const stopBtn = '<button onclick="svcAction('' + s.name + ''
|
|
569187
|
-
const disBtn = '<button onclick="svcAction('' + s.name + ''
|
|
569317
|
+
const stopBtn = '<button onclick="svcAction(\\'' + s.name + '\\',\\'stop\\')" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">stop</button>';
|
|
569318
|
+
const disBtn = '<button onclick="svcAction(\\'' + s.name + '\\',\\'disable\\')" style="background:#2a2a30;border:1px solid #5a2a2a;color:#b25f5f;padding:2px 6px;border-radius:3px;font-size:0.65rem;cursor:pointer">disable</button>';
|
|
569188
569319
|
return '<div style="background:#1e1e22;border-left:2px solid #3a3a42;padding:6px 10px;margin:4px 0;font-size:0.72rem">'
|
|
569189
569320
|
+ '<div style="color:#b0b0b0">' + s.name + '</div>'
|
|
569190
569321
|
+ '<div style="color:#555;font-size:0.6rem">enabled: ' + s.enabled + ' • active: ' + s.active + '</div>'
|
|
@@ -569195,7 +569326,7 @@ async function loadServices() {
|
|
|
569195
569326
|
} catch {}
|
|
569196
569327
|
}
|
|
569197
569328
|
|
|
569198
|
-
|
|
569329
|
+
window.svcAction = async function(name, action) {
|
|
569199
569330
|
try {
|
|
569200
569331
|
await fetch('/v1/services/systemd/' + encodeURIComponent(name), { method:'POST', headers: headers(), body: JSON.stringify({ action }) });
|
|
569201
569332
|
loadServices();
|
package/package.json
CHANGED