@songsid/agend 2.1.0-beta.26 โ 2.1.0-beta.28
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/backend/grok.js +3 -1
- package/dist/backend/grok.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +4 -0
- package/dist/classic-channel-manager.js +23 -0
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +31 -8
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +12 -0
- package/dist/daemon.js +40 -20
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +22 -2
- package/dist/fleet-manager.js +139 -5
- package/dist/fleet-manager.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +1 -0
- package/dist/instance-lifecycle.js +27 -6
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/pause-marker.d.ts +5 -0
- package/dist/pause-marker.js +36 -0
- package/dist/pause-marker.js.map +1 -0
- package/dist/settings-api.d.ts +2 -0
- package/dist/settings-api.js +102 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/ui/settings.html +153 -62
- package/package.json +1 -1
package/dist/ui/settings.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
--accent:#2563eb; --accent-hover:#1d4ed8; --green:#059669; --red:#dc2626; --yellow:#b45309;
|
|
12
12
|
--radius:8px; --radius-sm:6px;
|
|
13
13
|
}
|
|
14
|
-
body { background: var(--bg); color: var(--fg); font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 14px; line-height: 1.5; padding-bottom:
|
|
14
|
+
body { background: var(--bg); color: var(--fg); font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 14px; line-height: 1.5; padding-bottom: 88px; }
|
|
15
15
|
header { display: flex; align-items: center; gap: 12px; padding: 16px 24px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--bg); z-index: 20; }
|
|
16
16
|
header h1 { font-size: 18px; font-weight: 700; }
|
|
17
17
|
.grow { flex: 1; }
|
|
@@ -78,6 +78,18 @@
|
|
|
78
78
|
.inherit-row { display:flex; gap:8px; align-items:center; margin-top:6px; color:var(--muted); font-size:12px; }
|
|
79
79
|
.adv-body { display: none; padding: 14px 16px; }
|
|
80
80
|
.adv-body.open { display: block; }
|
|
81
|
+
.advanced-only { display:none !important; }
|
|
82
|
+
body.show-advanced .advanced-only { display:block !important; }
|
|
83
|
+
.more-menu { position:relative; }
|
|
84
|
+
.more-menu summary { list-style:none; cursor:pointer; padding:4px 9px; color:var(--muted); }
|
|
85
|
+
.more-menu summary::-webkit-details-marker { display:none; }
|
|
86
|
+
.more-menu .menu { position:absolute; right:0; top:30px; z-index:10; background:#fff; border:1px solid var(--border); border-radius:var(--radius-sm); box-shadow:0 8px 24px rgba(0,0,0,.12); padding:5px; min-width:130px; }
|
|
87
|
+
.more-menu .menu button { width:100%; text-align:left; border:0; }
|
|
88
|
+
.pending-bar { position:fixed; left:0; right:0; bottom:0; display:none; align-items:center; gap:12px; padding:12px max(16px, calc((100vw - 860px) / 2 + 24px)); background:#111827; color:#fff; z-index:35; box-shadow:0 -4px 18px rgba(0,0,0,.18); }
|
|
89
|
+
.pending-bar.open { display:flex; }
|
|
90
|
+
.pending-bar .grow { flex:1; }
|
|
91
|
+
.pending-bar button.primary { background:#fff; color:#111827; border-color:#fff; }
|
|
92
|
+
.level-label { font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:.4px; margin-bottom:8px; }
|
|
81
93
|
.toolbar { display: flex; gap: 6px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
|
|
82
94
|
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
|
|
83
95
|
.seg button { border: none; border-radius: 0; }
|
|
@@ -106,6 +118,9 @@
|
|
|
106
118
|
.sub { margin-left:0; } .field { padding:10px 12px; }
|
|
107
119
|
#agentSearch { width:130px !important; margin-right:0 !important; }
|
|
108
120
|
button { min-height:36px; } button.sm { min-height:32px; }
|
|
121
|
+
.pending-bar { padding:10px 12px; flex-wrap:wrap; }
|
|
122
|
+
.pending-bar .grow { display:none; }
|
|
123
|
+
.pending-bar button { flex:1; }
|
|
109
124
|
}
|
|
110
125
|
</style>
|
|
111
126
|
</head>
|
|
@@ -116,7 +131,7 @@
|
|
|
116
131
|
<div class="grow"></div>
|
|
117
132
|
<button class="help-btn" id="langBtn" title="Language">๐</button>
|
|
118
133
|
<button class="help-btn" id="helpBtn" title="Help">โน๏ธ</button>
|
|
119
|
-
<button id="
|
|
134
|
+
<button id="advancedToggle" title="Show additional controls">Show advanced</button>
|
|
120
135
|
</header>
|
|
121
136
|
<div class="help-backdrop" id="helpBackdrop"></div>
|
|
122
137
|
<aside class="help-panel" id="helpPanel">
|
|
@@ -137,7 +152,7 @@
|
|
|
137
152
|
</section>
|
|
138
153
|
|
|
139
154
|
<section>
|
|
140
|
-
<div class="sec-head"><h2
|
|
155
|
+
<div class="sec-head"><h2>๐ Connections & Bots</h2><div class="grow"></div><button class="sm advanced-only" id="newBotBtn" data-i18n="add">+ Add</button></div>
|
|
141
156
|
<div id="newBot"></div>
|
|
142
157
|
<div class="card" id="bots"></div>
|
|
143
158
|
</section>
|
|
@@ -148,15 +163,18 @@
|
|
|
148
163
|
</section>
|
|
149
164
|
|
|
150
165
|
<section>
|
|
151
|
-
<div class="
|
|
152
|
-
<div class="
|
|
153
|
-
</section>
|
|
154
|
-
|
|
155
|
-
<section>
|
|
156
|
-
<div class="sec-head"><h2 data-i18n="advanced">๐ Advanced</h2><div class="grow"></div><button class="sm" id="advToggle" data-i18n="expand">โถ Expand</button></div>
|
|
166
|
+
<div class="level-label">Developer ยท Level 3</div>
|
|
167
|
+
<div class="sec-head"><h2>๐ Developer YAML</h2><div class="grow"></div><button class="sm" id="advToggle" data-i18n="expand">โถ Expand</button></div>
|
|
157
168
|
<div class="card"><div class="adv-body" id="advBody"></div></div>
|
|
158
169
|
</section>
|
|
159
170
|
</main>
|
|
171
|
+
<div class="pending-bar" id="pendingBar">
|
|
172
|
+
<strong id="pendingCount">0 changes not applied</strong>
|
|
173
|
+
<span id="pendingImpact">โก Immediately ยท ๐ Restart this Agent ยท ๐๐ Restart AgEnD</span>
|
|
174
|
+
<span class="grow"></span>
|
|
175
|
+
<button id="discardChanges">Discard</button>
|
|
176
|
+
<button class="primary" id="applyChanges">Apply changes</button>
|
|
177
|
+
</div>
|
|
160
178
|
<script>
|
|
161
179
|
(() => {
|
|
162
180
|
"use strict";
|
|
@@ -228,7 +246,7 @@
|
|
|
228
246
|
document.querySelectorAll("[data-i18n]").forEach(e => { e.textContent = t(e.getAttribute("data-i18n")); });
|
|
229
247
|
document.querySelectorAll("[data-i18n-ph]").forEach(e => { e.setAttribute("placeholder", t(e.getAttribute("data-i18n-ph"))); });
|
|
230
248
|
// toggle labels that carry expand/collapse state
|
|
231
|
-
for (const [id, body] of [["advToggle", "advBody"]
|
|
249
|
+
for (const [id, body] of [["advToggle", "advBody"]]) {
|
|
232
250
|
const b = $(body); if (b) $(id).textContent = b.classList.contains("open") ? t("collapse") : t("expand");
|
|
233
251
|
}
|
|
234
252
|
renderHelp();
|
|
@@ -288,7 +306,7 @@
|
|
|
288
306
|
}
|
|
289
307
|
|
|
290
308
|
// โโ State โโ
|
|
291
|
-
const state = { fleet: {}, classic: {}, classicStatus: {}, live: {}, fleetUp: false, advFmt: "yaml", advEdit: false, collapsedGroups: new Set(), version: "", newAgentOpen: false, newBotOpen: false };
|
|
309
|
+
const state = { fleet: {}, classic: {}, classicStatus: {}, live: {}, fleetUp: false, advFmt: "yaml", advEdit: false, collapsedGroups: new Set(), version: "", newAgentOpen: false, newBotOpen: false, pending: new Map() };
|
|
292
310
|
const channels = () => state.fleet.channels || (state.fleet.channel ? [state.fleet.channel] : []);
|
|
293
311
|
const channelIds = () => channels().map(c => c.id || c.type).filter(Boolean);
|
|
294
312
|
const chLabel = (i) => i === 0 ? "primary" : "persona";
|
|
@@ -304,7 +322,36 @@
|
|
|
304
322
|
redraw(); return box;
|
|
305
323
|
}
|
|
306
324
|
function select(value, options) { const s = el("select"); for (const o of options) { const val = typeof o === "string" ? o : o.value; const label = typeof o === "string" ? o : o.label; const opt = el("option", {}, label); opt.value = val; if (val === value) opt.selected = true; s.append(opt); } return s; }
|
|
307
|
-
const impact = (kind) => el("span", { class: "impact" }, kind === "now" ? "โก
|
|
325
|
+
const impact = (kind) => el("span", { class: "impact" }, kind === "now" ? "โก Immediately" : kind === "fleet" ? "๐๐ Restart AgEnD" : "๐ Restart this Agent");
|
|
326
|
+
function updatePendingBar() {
|
|
327
|
+
const n = state.pending.size;
|
|
328
|
+
$("pendingBar").classList.toggle("open", n > 0);
|
|
329
|
+
$("pendingCount").textContent = `${n} change${n === 1 ? "" : "s"} not applied`;
|
|
330
|
+
const kinds = new Set([...state.pending.values()].map(change => change.impact));
|
|
331
|
+
$("pendingImpact").textContent = [...kinds].map(kind => kind === "now" ? "โก Immediately" : kind === "fleet" ? "๐๐ Restart AgEnD" : "๐ Restart this Agent").join(" ยท ");
|
|
332
|
+
}
|
|
333
|
+
function stageChange(key, change) {
|
|
334
|
+
state.pending.set(key, change);
|
|
335
|
+
updatePendingBar();
|
|
336
|
+
showBanner(`Queued: ${change.label}`);
|
|
337
|
+
}
|
|
338
|
+
async function applyPendingChanges() {
|
|
339
|
+
const button = $("applyChanges"); button.disabled = true;
|
|
340
|
+
for (const [key, change] of [...state.pending]) {
|
|
341
|
+
let result;
|
|
342
|
+
try { result = await change.apply(); }
|
|
343
|
+
catch (error) { result = { ok: false, body: { error: error.message } }; }
|
|
344
|
+
if (!result?.ok) {
|
|
345
|
+
showBanner(`${change.label}: ${result?.body?.error || "Apply failed"}`, true);
|
|
346
|
+
button.disabled = false; return;
|
|
347
|
+
}
|
|
348
|
+
state.pending.delete(key); updatePendingBar();
|
|
349
|
+
}
|
|
350
|
+
await api("/api/settings/reload", { method: "POST" });
|
|
351
|
+
await reload();
|
|
352
|
+
showBanner("โ Changes applied. AgEnD is reconciling affected Agents.");
|
|
353
|
+
button.disabled = false;
|
|
354
|
+
}
|
|
308
355
|
const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj || {}, key);
|
|
309
356
|
function overrideControl(inst, key, input, inheritedValue, impactKind = "instance") {
|
|
310
357
|
const inherited = !hasOwn(inst, key);
|
|
@@ -357,7 +404,9 @@
|
|
|
357
404
|
running ? el("button", { class: "sm", onclick: () => pauseWakeAgent(name, "pause") }, t("pause")) : null,
|
|
358
405
|
paused ? el("button", { class: "sm", onclick: () => pauseWakeAgent(name, "wake") }, t("wake")) : null,
|
|
359
406
|
!paused ? el("button", { class: "sm", onclick: () => toggleAgent(name, running) }, running ? t("stop") : t("start")) : null,
|
|
360
|
-
el("
|
|
407
|
+
el("details", { class: "more-menu" },
|
|
408
|
+
el("summary", { title: "More actions" }, "โฏ"),
|
|
409
|
+
el("div", { class: "menu" }, el("button", { class: "sm danger", onclick: () => delAgent(name) }, "Delete Agent"))),
|
|
361
410
|
));
|
|
362
411
|
if (editing === name) item.append(agentEditForm(name, inst));
|
|
363
412
|
return item;
|
|
@@ -443,27 +492,42 @@
|
|
|
443
492
|
model_failover: failover.toggle.checked ? null : (failover.input.value.trim() ? [failover.input.value.trim()] : []),
|
|
444
493
|
display_name: displayName.toggle.checked ? null : displayName.input.value.trim(),
|
|
445
494
|
};
|
|
446
|
-
|
|
447
|
-
|
|
495
|
+
state.fleet.instances[name] = { ...inst, ...patch };
|
|
496
|
+
for (const [key, value] of Object.entries(patch)) if (value === null) delete state.fleet.instances[name][key];
|
|
497
|
+
if (patch.hang_detector?.timeout_minutes === null) {
|
|
498
|
+
state.fleet.instances[name].hang_detector = { ...(inst.hang_detector || {}) };
|
|
499
|
+
delete state.fleet.instances[name].hang_detector.timeout_minutes;
|
|
500
|
+
}
|
|
501
|
+
stageChange(`agent:${name}`, {
|
|
502
|
+
label: `Update ${shortName(name, state.fleet.instances[name])}`,
|
|
503
|
+
impact: "instance",
|
|
504
|
+
apply: () => api(`/api/settings/fleet/instances/${encodeURIComponent(name)}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
|
505
|
+
});
|
|
506
|
+
editing = null; renderAgents();
|
|
448
507
|
};
|
|
449
508
|
box.append(
|
|
450
509
|
el("div", { class: "sub", style: "margin:0 0 8px" }, "ID: " + name),
|
|
451
|
-
el("div", { class: "grid2" },
|
|
510
|
+
el("div", { class: "grid2" },
|
|
511
|
+
el("div", {}, el("label", {}, t("displayName"), impact("now")), displayName.row),
|
|
512
|
+
el("div", {}, el("label", {}, t("description"), impact("now")), fDesc),
|
|
513
|
+
el("div", {}, el("label", {}, t("backend"), impact("instance")), fBackend),
|
|
514
|
+
el("div", {}, el("label", {}, t("model"), impact("instance")), fModel)),
|
|
452
515
|
el("label", {}, t("workingDir"), impact("instance")), fWd,
|
|
453
|
-
el("div", { class: "grid2" }, el("div", {}, el("label", {}, t("channelBinding"), impact("fleet")), fChan), el("div", {}, el("label", {}, t("description"), impact("now")), fDesc)),
|
|
454
|
-
el("label", {}, t("systemPrompt"), impact("instance")), fSys,
|
|
455
|
-
el("label", {}, t("tags"), impact("now")), chipList(tags, null, "tag"),
|
|
456
|
-
el("label", { style: "display:flex;align-items:center;gap:8px;cursor:pointer" }, fGeneral, el("span", {}, t("generalTopicField")), impact("fleet")),
|
|
457
|
-
el("div", { class: "sub", style: "margin:14px 0 6px;font-weight:600" }, t("runtimeResources")),
|
|
458
516
|
el("div", { class: "grid2" },
|
|
459
|
-
el("div", {}, el("label", {}, `${t("autoPause")} (${t("minutes")})
|
|
517
|
+
el("div", {}, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("instance")), auto.row, autoFeedback)),
|
|
518
|
+
el("div", { class: "advanced-only" },
|
|
519
|
+
el("div", { class: "sub", style: "margin:14px 0 6px;font-weight:600" }, "Advanced Agent settings"),
|
|
520
|
+
el("div", { class: "grid2" },
|
|
521
|
+
el("div", {}, el("label", {}, t("channelBinding"), impact("fleet")), fChan),
|
|
460
522
|
el("div", {}, el("label", {}, `${t("hangTimeout")} (${t("minutes")})`), hang.row, hangFeedback),
|
|
461
523
|
el("div", {}, el("label", {}, t("agentMode")), agentMode.row),
|
|
462
524
|
el("div", {}, el("label", {}, t("toolSet")), toolSet.row),
|
|
463
525
|
el("div", {}, el("label", {}, t("logLevel")), logLevel.row),
|
|
464
526
|
el("div", {}, el("label", {}, t("lightweight")), lightweight.row),
|
|
465
|
-
el("div", {}, el("label", {}, t("modelFailover")), failover.row, failoverFeedback),
|
|
466
|
-
el("
|
|
527
|
+
el("div", {}, el("label", {}, t("modelFailover")), failover.row, failoverFeedback)),
|
|
528
|
+
el("label", {}, t("systemPrompt"), impact("instance")), fSys,
|
|
529
|
+
el("label", {}, t("tags"), impact("now")), chipList(tags, null, "tag"),
|
|
530
|
+
el("label", { style: "display:flex;align-items:center;gap:8px;cursor:pointer" }, fGeneral, el("span", {}, t("generalTopicField")), impact("fleet"))),
|
|
467
531
|
el("div", { class: "actions" },
|
|
468
532
|
saveBtn,
|
|
469
533
|
el("button", { class: "sm ghost", onclick: () => { editing = null; renderAgents(); } }, t("cancel")),
|
|
@@ -483,9 +547,13 @@
|
|
|
483
547
|
await reloadLive();
|
|
484
548
|
}
|
|
485
549
|
async function delAgent(name) {
|
|
486
|
-
if (!confirm(`Delete agent "${name}"?
|
|
487
|
-
|
|
488
|
-
|
|
550
|
+
if (!confirm(`Delete agent "${name}"? This will be applied only after you confirm the pending changes.`)) return;
|
|
551
|
+
delete state.fleet.instances[name];
|
|
552
|
+
stageChange(`agent:${name}`, {
|
|
553
|
+
label: `Delete ${name}`, impact: "fleet",
|
|
554
|
+
apply: () => api(`/api/settings/fleet/instances/${encodeURIComponent(name)}`, { method: "DELETE" }),
|
|
555
|
+
});
|
|
556
|
+
renderAgents();
|
|
489
557
|
}
|
|
490
558
|
function renderNewAgent(open) {
|
|
491
559
|
const host = $("newAgent"); host.innerHTML = "";
|
|
@@ -520,12 +588,12 @@
|
|
|
520
588
|
const type = ch.type || "?";
|
|
521
589
|
item.append(el("div", { class: "item-row" },
|
|
522
590
|
el("span", { class: "name" }, type === "telegram" ? "Telegram" : "Discord"),
|
|
523
|
-
el("span", { class: "tag" + (i === 0 ? "" : " persona") + (type === "telegram" ? " tg" : "") }, chLabel(i)),
|
|
524
|
-
el("span", { class: "sub", style: "margin:0" }, ch.bot_token_env || "(no token env)"),
|
|
591
|
+
el("span", { class: "tag" + (i === 0 ? "" : " persona") + (type === "telegram" ? " tg" : "") }, ch.id || chLabel(i)),
|
|
592
|
+
el("span", { class: "sub advanced-only", style: "margin:0" }, ch.bot_token_env || "(no token env)"),
|
|
525
593
|
el("span", { class: "spacer" }),
|
|
526
|
-
el("span", { style: "
|
|
527
|
-
el("button", { class: "sm ghost", onclick: () => { editingBot = editingBot === i ? null : i; renderBots(); } }, editingBot === i ? t("close") : t("edit")),
|
|
528
|
-
el("button", { class: "sm danger", onclick: () => delBot(i) }, "
|
|
594
|
+
el("span", { style: `color:${state.fleetUp ? "var(--green)" : "var(--red)"};font-size:13px` }, state.fleetUp ? "Connected" : "Problem"),
|
|
595
|
+
el("button", { class: "sm ghost advanced-only", onclick: () => { editingBot = editingBot === i ? null : i; renderBots(); } }, editingBot === i ? t("close") : t("edit")),
|
|
596
|
+
el("button", { class: "sm danger advanced-only", onclick: () => delBot(i) }, "Delete"),
|
|
529
597
|
));
|
|
530
598
|
if (editingBot === i) item.append(botEditForm(ch, i));
|
|
531
599
|
host.append(item);
|
|
@@ -559,10 +627,10 @@
|
|
|
559
627
|
return box;
|
|
560
628
|
}
|
|
561
629
|
|
|
562
|
-
// โโ ClassicBot Channels
|
|
630
|
+
// โโ ClassicBot Channels โโ
|
|
563
631
|
function renderClassic() {
|
|
564
632
|
const host = $("classicList"); if (!host) return; host.innerHTML = "";
|
|
565
|
-
const chans = Object.
|
|
633
|
+
const chans = Object.entries(state.classic?.channels || {}).map(([key, channel]) => ({ key, ...channel }));
|
|
566
634
|
if (!chans.length) { host.className = "card empty"; host.textContent = t("noClassic"); return; }
|
|
567
635
|
const filter = ($("agentSearch")?.value || "").trim().toLowerCase();
|
|
568
636
|
let list = chans;
|
|
@@ -576,10 +644,20 @@
|
|
|
576
644
|
for (const c of list) {
|
|
577
645
|
const st = state.classicStatus[c.instanceName] || "stopped";
|
|
578
646
|
const adapter = c.adapterId || "discord";
|
|
647
|
+
const backend = select(c.backend || state.classic?.defaults?.backend || "claude-code", BACKENDS.filter(value => value !== "gemini-cli"));
|
|
648
|
+
backend.style.width = "150px";
|
|
649
|
+
backend.onchange = () => {
|
|
650
|
+
const value = backend.value;
|
|
651
|
+
state.classic.channels[c.key].backend = value;
|
|
652
|
+
stageChange(`classic:${c.key}`, {
|
|
653
|
+
label: `Change ${c.name || c.instanceName} backend`, impact: "instance",
|
|
654
|
+
apply: () => api(`/api/settings/classic/channels/${encodeURIComponent(c.key)}`, { method: "PATCH", body: JSON.stringify({ backend: value }) }),
|
|
655
|
+
});
|
|
656
|
+
};
|
|
579
657
|
host.append(el("div", { class: "item" }, el("div", { class: "item-row" },
|
|
580
658
|
el("span", { class: "dot " + st, title: STATUS_TEXT[st] || st }),
|
|
581
659
|
el("span", { class: "name", title: c.instanceName || "" }, c.name || c.instanceName || "?"),
|
|
582
|
-
|
|
660
|
+
backend,
|
|
583
661
|
el("span", { class: "tag" + (adapter !== "discord" ? " persona" : "") }, adapter),
|
|
584
662
|
c.collab ? el("span", { class: "tag", style: "background:#ecfdf5;color:#065f46" }, "collab") : null,
|
|
585
663
|
)));
|
|
@@ -635,6 +713,7 @@
|
|
|
635
713
|
c.admin_users = c.admin_users || []; c.allowed_guilds = c.allowed_guilds || [];
|
|
636
714
|
|
|
637
715
|
const fBackend = select(d.backend || "claude-code", BACKENDS);
|
|
716
|
+
const fClassicBackend = select(c.backend || d.backend || "claude-code", BACKENDS.filter(value => value !== "gemini-cli"));
|
|
638
717
|
const fModel = el("input", { type: "text", value: d.model || "", placeholder: "e.g. claude-opus-4-8" });
|
|
639
718
|
const fAgentMode = select(d.agent_mode || "mcp", ["mcp", "cli"]);
|
|
640
719
|
const fToolSet = select(d.tool_set || "full", ["full", "standard", "minimal"]);
|
|
@@ -665,7 +744,8 @@
|
|
|
665
744
|
for (const input of [fAutoPause, fHangTimeout, fConcurrency, fStagger]) {
|
|
666
745
|
input.addEventListener("input", validate); input.addEventListener("change", validate);
|
|
667
746
|
}
|
|
668
|
-
saveBtn.
|
|
747
|
+
saveBtn.textContent = "Review changes";
|
|
748
|
+
saveBtn.onclick = () => {
|
|
669
749
|
if (!validate()) return;
|
|
670
750
|
const defaultsPatch = {
|
|
671
751
|
backend: fBackend.value,
|
|
@@ -678,17 +758,13 @@
|
|
|
678
758
|
hang_detector: { enabled: fHangEnabled.checked, timeout_minutes: Number(fHangTimeout.value) },
|
|
679
759
|
startup: { concurrency: Number(fConcurrency.value), stagger_delay_ms: Number(fStagger.value) },
|
|
680
760
|
};
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
const affected = Object.keys(state.fleet.instances || {});
|
|
689
|
-
await reload();
|
|
690
|
-
showBanner(`โ ${t("affected")}: ${affected.length ? affected.join(", ") : "none"} โ ๐ restart instances; startup changes ๐๐ restart fleet`);
|
|
691
|
-
}
|
|
761
|
+
const classicPatch = { backend: fClassicBackend.value, admin_users: c.admin_users, allowed_guilds: c.allowed_guilds };
|
|
762
|
+
state.fleet.defaults = { ...d, ...defaultsPatch };
|
|
763
|
+
state.classic.defaults = { ...c, ...classicPatch };
|
|
764
|
+
stageChange("defaults:fleet", { label: "Update Agent defaults", impact: "instance", apply: () => api("/api/settings/fleet/defaults", { method: "PUT", body: JSON.stringify(defaultsPatch) }) });
|
|
765
|
+
if (primary) stageChange("connections:primary", { label: "Update primary connection access", impact: "fleet", apply: () => api("/api/settings/fleet/channels", { method: "PUT", body: JSON.stringify(channels()) }) });
|
|
766
|
+
stageChange("defaults:classic", { label: "Update ClassicBot defaults and access", impact: "fleet", apply: () => api("/api/settings/classic/defaults", { method: "PUT", body: JSON.stringify(classicPatch) }) });
|
|
767
|
+
msg.innerHTML = `<span class="s">Ready to apply</span>`;
|
|
692
768
|
};
|
|
693
769
|
|
|
694
770
|
const section = (title, open, ...children) => {
|
|
@@ -697,15 +773,24 @@
|
|
|
697
773
|
return details;
|
|
698
774
|
};
|
|
699
775
|
host.append(
|
|
700
|
-
section(
|
|
701
|
-
el("div", { class: "grid2" },
|
|
702
|
-
el("div", { class: "field" }, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("instance")), fAutoPause, autoFeedback),
|
|
703
|
-
el("div", { class: "field" }, el("label", {}, t("toolSet"), impact("instance")), fToolSet),
|
|
704
|
-
el("div", { class: "field" }, el("label", {}, t("logLevel"), impact("instance")), fLogLevel))),
|
|
705
|
-
section(t("backendSection"), true,
|
|
776
|
+
section("Defaults", true,
|
|
706
777
|
el("div", { class: "grid2" },
|
|
778
|
+
el("div", { class: "field" }, el("label", {}, t("language"), impact("now")), fLocale),
|
|
707
779
|
el("div", { class: "field" }, el("label", {}, t("defaultBackend"), impact("instance")), fBackend),
|
|
708
780
|
el("div", { class: "field" }, el("label", {}, t("defaultModel"), impact("instance")), fModel),
|
|
781
|
+
el("div", { class: "field" }, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("instance")), fAutoPause, autoFeedback))),
|
|
782
|
+
section("ClassicBot", true,
|
|
783
|
+
el("div", { class: "grid2" },
|
|
784
|
+
el("div", { class: "field" }, el("label", {}, "Classic default backend", impact("instance")), fClassicBackend)),
|
|
785
|
+
el("div", { class: "field" }, el("strong", {}, "Who can use ClassicBot"),
|
|
786
|
+
el("div", { class: "grid2" },
|
|
787
|
+
el("div", {}, el("label", {}, t("classicAdmins"), impact("fleet")), chipList(c.admin_users, null, "user id")),
|
|
788
|
+
el("div", {}, el("label", {}, t("allowedGuilds"), impact("fleet")), chipList(c.allowed_guilds, null, "guild id"))))),
|
|
789
|
+
el("div", { class: "advanced-only" },
|
|
790
|
+
section(t("runtimeResources"), false,
|
|
791
|
+
el("div", { class: "grid2" },
|
|
792
|
+
el("div", { class: "field" }, el("label", {}, t("toolSet"), impact("instance")), fToolSet),
|
|
793
|
+
el("div", { class: "field" }, el("label", {}, t("logLevel"), impact("instance")), fLogLevel),
|
|
709
794
|
el("div", { class: "field" }, el("label", {}, t("agentMode"), impact("instance")), fAgentMode))),
|
|
710
795
|
section(t("detection"), false,
|
|
711
796
|
el("div", { class: "grid2" },
|
|
@@ -715,11 +800,8 @@
|
|
|
715
800
|
el("div", { class: "grid2" },
|
|
716
801
|
el("div", { class: "field" }, el("label", {}, t("concurrency"), impact("fleet")), fConcurrency, concurrencyFeedback),
|
|
717
802
|
el("div", { class: "field" }, el("label", {}, `${t("staggerDelay")} (ms)`, impact("fleet")), fStagger, staggerFeedback))),
|
|
718
|
-
section(
|
|
719
|
-
el("div", { class: "field" }, el("label", {}, t("
|
|
720
|
-
el("div", { class: "field" }, el("label", {}, t("allowedUsers"), impact("fleet")), chipList(allowedUsers, null, "user id")),
|
|
721
|
-
el("div", { class: "field" }, el("label", {}, t("classicAdmins"), impact("fleet")), chipList(c.admin_users, null, "user id")),
|
|
722
|
-
el("div", { class: "field" }, el("label", {}, t("allowedGuilds"), impact("fleet")), chipList(c.allowed_guilds, null, "guild id"))),
|
|
803
|
+
section("Advanced & Access", false,
|
|
804
|
+
el("div", { class: "field" }, el("label", {}, t("allowedUsers"), impact("fleet")), chipList(allowedUsers, null, "user id")))),
|
|
723
805
|
el("div", { class: "field" }, el("div", { class: "actions" }, saveBtn, msg)),
|
|
724
806
|
);
|
|
725
807
|
validate();
|
|
@@ -786,7 +868,7 @@
|
|
|
786
868
|
}
|
|
787
869
|
|
|
788
870
|
// โโ Load / render โโ
|
|
789
|
-
function renderAll() { renderAgents(); renderClassic(); renderBots(); renderGeneral();
|
|
871
|
+
function renderAll() { renderAgents(); renderClassic(); renderBots(); renderGeneral(); renderAdvanced(); applyStaticI18n(); }
|
|
790
872
|
async function reloadLive() {
|
|
791
873
|
const f = await api("/api/fleet");
|
|
792
874
|
state.fleetUp = f.ok;
|
|
@@ -813,13 +895,22 @@
|
|
|
813
895
|
$("helpClose").onclick = () => setHelp(false);
|
|
814
896
|
$("helpBackdrop").onclick = () => setHelp(false);
|
|
815
897
|
$("langBtn").onclick = () => { lang = lang === "en" ? "zh-TW" : "en"; localStorage.setItem("agend_lang", lang); renderAll(); };
|
|
816
|
-
$("verBadge").onclick = () =>
|
|
898
|
+
$("verBadge").onclick = () => window.open("https://github.com/songsid/AgEnD/releases/latest", "_blank", "noopener");
|
|
817
899
|
$("agentSearch").oninput = () => { renderAgents(); renderClassic(); };
|
|
818
900
|
$("newAgentBtn").onclick = () => { state.newAgentOpen = !state.newAgentOpen; $("newAgentBtn").textContent = state.newAgentOpen ? t("cancel") : t("new"); renderNewAgent(state.newAgentOpen); };
|
|
819
901
|
$("newBotBtn").onclick = () => { state.newBotOpen = !state.newBotOpen; $("newBotBtn").textContent = state.newBotOpen ? t("cancel") : t("add"); renderNewBot(state.newBotOpen); };
|
|
820
902
|
$("advToggle").onclick = () => { const b = $("advBody"); const open = !b.classList.contains("open"); b.classList.toggle("open", open); $("advToggle").textContent = open ? t("collapse") : t("expand"); };
|
|
821
|
-
|
|
822
|
-
|
|
903
|
+
const advancedEnabled = localStorage.getItem("agend_settings_advanced") === "true";
|
|
904
|
+
document.body.classList.toggle("show-advanced", advancedEnabled);
|
|
905
|
+
$("advancedToggle").textContent = advancedEnabled ? "Hide advanced" : "Show advanced";
|
|
906
|
+
$("advancedToggle").onclick = () => {
|
|
907
|
+
const enabled = !document.body.classList.contains("show-advanced");
|
|
908
|
+
document.body.classList.toggle("show-advanced", enabled);
|
|
909
|
+
localStorage.setItem("agend_settings_advanced", String(enabled));
|
|
910
|
+
$("advancedToggle").textContent = enabled ? "Hide advanced" : "Show advanced";
|
|
911
|
+
};
|
|
912
|
+
$("applyChanges").onclick = applyPendingChanges;
|
|
913
|
+
$("discardChanges").onclick = async () => { state.pending.clear(); updatePendingBar(); await reload(); };
|
|
823
914
|
|
|
824
915
|
reload();
|
|
825
916
|
})();
|