@songsid/agend 2.1.5-beta.21 → 2.1.5-beta.22
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/channel/adapters/telegram.d.ts +16 -0
- package/dist/channel/adapters/telegram.js +47 -5
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/types.d.ts +1 -0
- package/dist/classic-channel-manager.d.ts +23 -3
- package/dist/classic-channel-manager.js +35 -0
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/config-validator.js +15 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.js +8 -1
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +42 -1
- package/dist/fleet-manager.js +259 -54
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +26 -2
- package/dist/locale.js +2 -2
- package/dist/locale.js.map +1 -1
- package/dist/settings-api.d.ts +1 -1
- package/dist/settings-api.js +38 -6
- package/dist/settings-api.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/ui/dashboard.html +7 -5
- package/dist/ui/settings.html +93 -15
- package/dist/ui/view.html +8 -7
- package/package.json +1 -1
package/dist/ui/settings.html
CHANGED
|
@@ -194,7 +194,7 @@
|
|
|
194
194
|
backend: "Backend", model: "Model", workingDir: "Working directory", channelBinding: "Channel binding",
|
|
195
195
|
description: "Description", systemPrompt: "System prompt", tags: "Tags", generalTopicField: "General topic (fleet dispatcher)",
|
|
196
196
|
runtimeResources: "Runtime & Resources", autoPause: "Auto-pause after", minutes: "minutes", inheritDefault: "Inherit from defaults",
|
|
197
|
-
detection: "Detection", startup: "Startup", backendSection: "Backend", advancedSection: "Advanced & Access", hangEnabled: "Hang detector enabled", hangTimeout: "Stuck timeout", agentMode: "Agent mode", toolSet: "Tool set", toolProgress: "Tool progress", logLevel: "Log level", concurrency: "Startup concurrency", staggerDelay: "Stagger delay", lightweight: "Lightweight mode", modelFailover: "Fallback model", displayName: "Display name", pause: "Pause", wake: "Wake", accessMode: "Access mode", affected: "Affected instances",
|
|
197
|
+
detection: "Detection", startup: "Startup", backendSection: "Backend", advancedSection: "Advanced & Access", hangEnabled: "Hang detector enabled", hangTimeout: "Stuck timeout", agentMode: "Agent mode", toolSet: "Tool set", toolProgress: "Tool progress", replyCompletionGuard: "Require a delivered reply", replyGuardSupported: "Active for Claude Code in MCP mode.", replyGuardUnsupported: "Stored but inactive: {0} in {1} mode does not support reply-drop recovery.", logLevel: "Log level", concurrency: "Startup concurrency", staggerDelay: "Stagger delay", lightweight: "Lightweight mode", modelFailover: "Fallback model", displayName: "Display name", pause: "Pause", wake: "Wake", accessMode: "Access mode", affected: "Affected instances",
|
|
198
198
|
language: "Language (bot replies)", defaultBackend: "Default backend", defaultModel: "Default model", allowedUsers: "Allowed users (primary bot)",
|
|
199
199
|
classicAdmins: "ClassicBot admins", allowedGuilds: "Allowed guilds", type: "Type", adapterId: "Adapter id",
|
|
200
200
|
tokenEnv: "Bot token env var", groupId: "Group / guild id", nameField: "Name",
|
|
@@ -216,7 +216,7 @@
|
|
|
216
216
|
backend: "後端", model: "模型", workingDir: "工作目錄", channelBinding: "頻道綁定",
|
|
217
217
|
description: "描述", systemPrompt: "System prompt", tags: "標籤", generalTopicField: "General topic(fleet 分派器)",
|
|
218
218
|
runtimeResources: "執行環境與資源", autoPause: "閒置後自動暫停", minutes: "分鐘", inheritDefault: "沿用全域預設值",
|
|
219
|
-
detection: "偵測", startup: "啟動", backendSection: "後端", advancedSection: "進階與存取", hangEnabled: "啟用卡住偵測", hangTimeout: "卡住逾時", agentMode: "Agent 模式", toolSet: "工具集", toolProgress: "工具進度", logLevel: "Log 等級", concurrency: "啟動併發數", staggerDelay: "錯開延遲", lightweight: "輕量模式", modelFailover: "備援模型", displayName: "顯示名稱", pause: "暫停", wake: "喚醒", accessMode: "存取模式", affected: "受影響 instances",
|
|
219
|
+
detection: "偵測", startup: "啟動", backendSection: "後端", advancedSection: "進階與存取", hangEnabled: "啟用卡住偵測", hangTimeout: "卡住逾時", agentMode: "Agent 模式", toolSet: "工具集", toolProgress: "工具進度", replyCompletionGuard: "要求送出回覆", replyGuardSupported: "Claude Code 的 MCP 模式可用。", replyGuardUnsupported: "設定會保留,但不會生效:{0} 的 {1} 模式不支援回覆遺失補救。", logLevel: "Log 等級", concurrency: "啟動併發數", staggerDelay: "錯開延遲", lightweight: "輕量模式", modelFailover: "備援模型", displayName: "顯示名稱", pause: "暫停", wake: "喚醒", accessMode: "存取模式", affected: "受影響 instances",
|
|
220
220
|
language: "語言(bot 回覆)", defaultBackend: "預設後端", defaultModel: "預設模型", allowedUsers: "允許使用者(主 bot)",
|
|
221
221
|
classicAdmins: "ClassicBot 管理員", allowedGuilds: "允許的伺服器", type: "類型", adapterId: "Adapter id",
|
|
222
222
|
tokenEnv: "Bot token 環境變數", groupId: "群組 / guild id", nameField: "名稱",
|
|
@@ -373,7 +373,7 @@
|
|
|
373
373
|
button.disabled = false;
|
|
374
374
|
}
|
|
375
375
|
const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj || {}, key);
|
|
376
|
-
const HOT_FIELDS = new Set(["tool_progress", "mcp_proxy_reply", "auto_pause_after", "warm_cap", "display_name", "description", "tags", "log_level"]);
|
|
376
|
+
const HOT_FIELDS = new Set(["tool_progress", "reply_completion_guard", "mcp_proxy_reply", "auto_pause_after", "warm_cap", "display_name", "description", "tags", "log_level"]);
|
|
377
377
|
const sameValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
378
378
|
function changedFields(next, baseline) {
|
|
379
379
|
return Object.fromEntries(Object.entries(next).filter(([key, value]) => !sameValue(value, baseline[key])));
|
|
@@ -389,6 +389,12 @@
|
|
|
389
389
|
toggle.onchange = () => { input.disabled = toggle.checked; };
|
|
390
390
|
return { input, toggle, row: el("div", {}, input, el("label", { class: "inherit-row" }, toggle, el("span", {}, t("inheritDefault")), impact(impactKind))) };
|
|
391
391
|
}
|
|
392
|
+
const replyGuardSupported = (backend, mode) => backend === "claude-code" && mode === "mcp";
|
|
393
|
+
const replyGuardHint = (backend, mode) => el(
|
|
394
|
+
"div",
|
|
395
|
+
{ class: "hint" },
|
|
396
|
+
replyGuardSupported(backend, mode) ? t("replyGuardSupported") : tf("replyGuardUnsupported", backend, mode),
|
|
397
|
+
);
|
|
392
398
|
function setValidation(input, feedback, error, warning) {
|
|
393
399
|
input.classList.toggle("invalid", !!error);
|
|
394
400
|
feedback.className = "feedback" + (error ? " error" : warning ? " warning" : "");
|
|
@@ -501,7 +507,17 @@
|
|
|
501
507
|
const hang = overrideControl(hangHolder, "value", el("input", { type: "number", min: "0.1", step: "0.5", value: hangRaw.timeout_minutes ?? defaults.hang_detector?.timeout_minutes ?? 15 }), defaults.hang_detector?.timeout_minutes ?? 15);
|
|
502
508
|
const agentMode = overrideControl(inst, "agent_mode", select(inst.agent_mode || defaults.agent_mode || "mcp", ["mcp", "cli"]), defaults.agent_mode || "mcp");
|
|
503
509
|
const toolSet = overrideControl(inst, "tool_set", select(inst.tool_set || defaults.tool_set || "full", ["full", "standard", "minimal"]), defaults.tool_set || "full");
|
|
504
|
-
const toolProgress = overrideControl(inst, "tool_progress", select(inst.tool_progress
|
|
510
|
+
const toolProgress = overrideControl(inst, "tool_progress", select(inst.tool_progress ?? defaults.tool_progress ?? "off", ["off", "standard", "verbose"]), defaults.tool_progress ?? "off", "now");
|
|
511
|
+
const fReplyGuard = el("input", { type: "checkbox" });
|
|
512
|
+
fReplyGuard.checked = inst.reply_completion_guard ?? defaults.reply_completion_guard ?? true;
|
|
513
|
+
const replyGuard = overrideControl(inst, "reply_completion_guard", fReplyGuard, defaults.reply_completion_guard ?? true, "now");
|
|
514
|
+
const replyHint = replyGuardHint(fBackend.value, agentMode.input.value);
|
|
515
|
+
const refreshReplyHint = () => {
|
|
516
|
+
const supported = replyGuardSupported(fBackend.value, agentMode.input.value);
|
|
517
|
+
replyHint.textContent = supported ? t("replyGuardSupported") : tf("replyGuardUnsupported", fBackend.value, agentMode.input.value);
|
|
518
|
+
};
|
|
519
|
+
fBackend.addEventListener("change", refreshReplyHint);
|
|
520
|
+
agentMode.input.addEventListener("change", refreshReplyHint);
|
|
505
521
|
const logLevel = overrideControl(inst, "log_level", select(inst.log_level || defaults.log_level || "info", ["trace", "debug", "info", "warn", "error"]), defaults.log_level || "info");
|
|
506
522
|
const fLightweight = el("input", { type: "checkbox" }); fLightweight.checked = inst.lightweight ?? defaults.lightweight ?? false;
|
|
507
523
|
const lightweight = overrideControl(inst, "lightweight", fLightweight, defaults.lightweight ?? false);
|
|
@@ -521,7 +537,7 @@
|
|
|
521
537
|
saveBtn.disabled = !(validAuto && validHang);
|
|
522
538
|
return !saveBtn.disabled;
|
|
523
539
|
};
|
|
524
|
-
for (const ctl of [auto, hang, agentMode, toolSet, toolProgress, logLevel, lightweight, failover, displayName]) {
|
|
540
|
+
for (const ctl of [auto, hang, agentMode, toolSet, toolProgress, replyGuard, logLevel, lightweight, failover, displayName]) {
|
|
525
541
|
ctl.input.addEventListener("input", validate); ctl.input.addEventListener("change", validate); ctl.toggle.addEventListener("change", validate);
|
|
526
542
|
}
|
|
527
543
|
saveBtn.onclick = async () => {
|
|
@@ -536,6 +552,7 @@
|
|
|
536
552
|
agent_mode: agentMode.toggle.checked ? null : agentMode.input.value,
|
|
537
553
|
tool_set: toolSet.toggle.checked ? null : toolSet.input.value,
|
|
538
554
|
tool_progress: toolProgress.toggle.checked ? null : toolProgress.input.value,
|
|
555
|
+
reply_completion_guard: replyGuard.toggle.checked ? null : replyGuard.input.checked,
|
|
539
556
|
log_level: logLevel.toggle.checked ? null : logLevel.input.value,
|
|
540
557
|
lightweight: lightweight.toggle.checked ? null : lightweight.input.checked,
|
|
541
558
|
model_failover: failover.toggle.checked ? null : (failover.input.value.trim() ? [failover.input.value.trim()] : []),
|
|
@@ -555,6 +572,7 @@
|
|
|
555
572
|
agent_mode: hasOwn(inst, "agent_mode") ? inst.agent_mode : null,
|
|
556
573
|
tool_set: hasOwn(inst, "tool_set") ? inst.tool_set : null,
|
|
557
574
|
tool_progress: hasOwn(inst, "tool_progress") ? inst.tool_progress : null,
|
|
575
|
+
reply_completion_guard: hasOwn(inst, "reply_completion_guard") ? inst.reply_completion_guard : null,
|
|
558
576
|
log_level: hasOwn(inst, "log_level") ? inst.log_level : null,
|
|
559
577
|
lightweight: hasOwn(inst, "lightweight") ? inst.lightweight : null,
|
|
560
578
|
model_failover: hasOwn(inst, "model_failover") ? inst.model_failover : null,
|
|
@@ -591,6 +609,7 @@
|
|
|
591
609
|
el("div", {}, el("label", {}, t("agentMode")), agentMode.row),
|
|
592
610
|
el("div", {}, el("label", {}, t("toolSet")), toolSet.row),
|
|
593
611
|
el("div", {}, el("label", {}, t("toolProgress"), impact("now")), toolProgress.row),
|
|
612
|
+
el("div", {}, el("label", {}, t("replyCompletionGuard"), impact("now")), replyGuard.row, replyHint),
|
|
594
613
|
el("div", {}, el("label", {}, t("logLevel"), impact("now")), logLevel.row),
|
|
595
614
|
el("div", {}, el("label", {}, t("lightweight")), lightweight.row),
|
|
596
615
|
el("div", {}, el("label", {}, t("modelFailover")), failover.row, failoverFeedback)),
|
|
@@ -717,10 +736,22 @@
|
|
|
717
736
|
const inheritedBackend = classicDefaults.backend || fleetDefaults.backend || "claude-code";
|
|
718
737
|
const inheritedModel = classicDefaults.model || fleetDefaults.model || "";
|
|
719
738
|
const inheritedAutoPause = classicDefaults.auto_pause_after ?? fleetDefaults.auto_pause_after ?? 0;
|
|
739
|
+
const inheritedToolProgress = classicDefaults.tool_progress ?? fleetDefaults.tool_progress ?? "off";
|
|
740
|
+
const inheritedReplyGuard = classicDefaults.reply_completion_guard ?? fleetDefaults.reply_completion_guard ?? true;
|
|
720
741
|
const runtime = classicRuntime(c.instanceName);
|
|
721
742
|
const fBackend = select(c.backend || inheritedBackend, BACKENDS.filter(value => value !== "gemini-cli"));
|
|
722
743
|
const fModel = el("input", { type: "text", value: c.model || "", placeholder: inheritedModel || "(inherit default)" });
|
|
723
744
|
const auto = overrideControl(c, "auto_pause_after", el("input", { type: "number", min: "0", step: "1", value: c.auto_pause_after ?? inheritedAutoPause, placeholder: "0 = disabled" }), inheritedAutoPause);
|
|
745
|
+
const toolProgress = overrideControl(c, "tool_progress", select(c.tool_progress ?? inheritedToolProgress, ["off", "standard", "verbose"]), inheritedToolProgress, "now");
|
|
746
|
+
const fReplyGuard = el("input", { type: "checkbox" });
|
|
747
|
+
fReplyGuard.checked = c.reply_completion_guard ?? inheritedReplyGuard;
|
|
748
|
+
const replyGuard = overrideControl(c, "reply_completion_guard", fReplyGuard, inheritedReplyGuard, "now");
|
|
749
|
+
const classicMode = fleetDefaults.agent_mode ?? "mcp";
|
|
750
|
+
const replyHint = replyGuardHint(fBackend.value, classicMode);
|
|
751
|
+
fBackend.addEventListener("change", () => {
|
|
752
|
+
const supported = replyGuardSupported(fBackend.value, classicMode);
|
|
753
|
+
replyHint.textContent = supported ? t("replyGuardSupported") : tf("replyGuardUnsupported", fBackend.value, classicMode);
|
|
754
|
+
});
|
|
724
755
|
const fCollab = el("input", { type: "checkbox" }); fCollab.checked = !!c.collab;
|
|
725
756
|
const fContext = el("input", { type: "number", min: "0", step: "1", value: c.context_lines ?? classicDefaults.context_lines ?? 5 });
|
|
726
757
|
const autoFeedback = el("div", { class: "feedback" });
|
|
@@ -734,24 +765,39 @@
|
|
|
734
765
|
saveBtn.disabled = !(validAuto && validContext);
|
|
735
766
|
return !saveBtn.disabled;
|
|
736
767
|
};
|
|
737
|
-
for (const input of [fBackend, fModel, auto.input, auto.toggle, fCollab, fContext]) {
|
|
768
|
+
for (const input of [fBackend, fModel, auto.input, auto.toggle, toolProgress.input, toolProgress.toggle, replyGuard.input, replyGuard.toggle, fCollab, fContext]) {
|
|
738
769
|
input.addEventListener("input", validate); input.addEventListener("change", validate);
|
|
739
770
|
}
|
|
740
771
|
saveBtn.onclick = () => {
|
|
741
772
|
if (!validate()) return;
|
|
742
|
-
const
|
|
773
|
+
const nextPatch = {
|
|
743
774
|
backend: fBackend.value,
|
|
744
775
|
model: fModel.value.trim() || null,
|
|
745
776
|
auto_pause_after: auto.toggle.checked ? null : Number(auto.input.value),
|
|
777
|
+
tool_progress: toolProgress.toggle.checked ? null : toolProgress.input.value,
|
|
778
|
+
reply_completion_guard: replyGuard.toggle.checked ? null : replyGuard.input.checked,
|
|
746
779
|
collab: fCollab.checked,
|
|
747
780
|
context_lines: Number(fContext.value),
|
|
748
781
|
};
|
|
782
|
+
const patch = changedFields(nextPatch, {
|
|
783
|
+
backend: c.backend || inheritedBackend,
|
|
784
|
+
model: c.model?.trim() || null,
|
|
785
|
+
auto_pause_after: hasOwn(c, "auto_pause_after") ? c.auto_pause_after : null,
|
|
786
|
+
tool_progress: hasOwn(c, "tool_progress") ? c.tool_progress : null,
|
|
787
|
+
reply_completion_guard: hasOwn(c, "reply_completion_guard") ? c.reply_completion_guard : null,
|
|
788
|
+
collab: !!c.collab,
|
|
789
|
+
context_lines: c.context_lines ?? classicDefaults.context_lines ?? 5,
|
|
790
|
+
});
|
|
791
|
+
if (Object.keys(patch).length === 0) { editingClassic = null; renderClassic(); return; }
|
|
749
792
|
state.classic.channels[c.key] = { ...state.classic.channels[c.key], ...patch };
|
|
750
793
|
if (patch.model === null) delete state.classic.channels[c.key].model;
|
|
751
794
|
if (patch.auto_pause_after === null) delete state.classic.channels[c.key].auto_pause_after;
|
|
795
|
+
if (patch.tool_progress === null) delete state.classic.channels[c.key].tool_progress;
|
|
796
|
+
if (patch.reply_completion_guard === null) delete state.classic.channels[c.key].reply_completion_guard;
|
|
797
|
+
const hotOnly = Object.keys(patch).every(key => key === "tool_progress" || key === "reply_completion_guard");
|
|
752
798
|
stageChange(`classic:${c.key}`, {
|
|
753
799
|
label: `Update ${c.name || c.instanceName}`,
|
|
754
|
-
impact: "instance",
|
|
800
|
+
impact: hotOnly ? "now" : "instance",
|
|
755
801
|
apply: () => api(`/api/settings/classic/channels/${encodeURIComponent(c.key)}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
|
756
802
|
});
|
|
757
803
|
editingClassic = null;
|
|
@@ -763,6 +809,8 @@
|
|
|
763
809
|
el("div", {}, el("label", {}, t("backend"), impact("instance")), fBackend),
|
|
764
810
|
el("div", {}, el("label", {}, t("model"), impact("instance")), fModel),
|
|
765
811
|
el("div", {}, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("instance")), auto.row, autoFeedback),
|
|
812
|
+
el("div", {}, el("label", {}, t("toolProgress"), impact("now")), toolProgress.row),
|
|
813
|
+
el("div", {}, el("label", {}, t("replyCompletionGuard"), impact("now")), replyGuard.row, replyHint),
|
|
766
814
|
el("div", {}, el("label", { style: "display:flex;align-items:center;gap:8px;cursor:pointer;margin-top:28px" }, fCollab, el("span", {}, "Collaboration mode"), impact("instance")))),
|
|
767
815
|
el("div", { class: "advanced-only" },
|
|
768
816
|
el("label", {}, "Context lines", impact("instance")), fContext, contextFeedback),
|
|
@@ -872,7 +920,11 @@
|
|
|
872
920
|
const fModel = el("input", { type: "text", value: d.model || "", placeholder: "e.g. claude-opus-4-8" });
|
|
873
921
|
const fAgentMode = select(d.agent_mode || "mcp", ["mcp", "cli"]);
|
|
874
922
|
const fToolSet = select(d.tool_set || "full", ["full", "standard", "minimal"]);
|
|
875
|
-
const fToolProgress = select(d.tool_progress
|
|
923
|
+
const fToolProgress = select(d.tool_progress ?? "off", ["off", "standard", "verbose"]);
|
|
924
|
+
const fReplyGuard = el("input", { type: "checkbox" }); fReplyGuard.checked = d.reply_completion_guard ?? true;
|
|
925
|
+
const fClassicToolProgress = overrideControl(c, "tool_progress", select(c.tool_progress ?? d.tool_progress ?? "off", ["off", "standard", "verbose"]), d.tool_progress ?? "off", "now");
|
|
926
|
+
const fClassicReplyInput = el("input", { type: "checkbox" }); fClassicReplyInput.checked = c.reply_completion_guard ?? d.reply_completion_guard ?? true;
|
|
927
|
+
const fClassicReplyGuard = overrideControl(c, "reply_completion_guard", fClassicReplyInput, d.reply_completion_guard ?? true, "now");
|
|
876
928
|
const fAccessMode = select(originalPrimaryAccess.mode || "locked", ["locked", "open", "pairing"]);
|
|
877
929
|
const fLogLevel = select(d.log_level || "info", ["trace", "debug", "info", "warn", "error"]);
|
|
878
930
|
const fLocale = el("select");
|
|
@@ -889,6 +941,17 @@
|
|
|
889
941
|
const staggerFeedback = el("div", { class: "feedback" });
|
|
890
942
|
const accessFeedback = el("div", { class: "feedback" });
|
|
891
943
|
const saveBtn = el("button", { class: "primary" }, t("save"));
|
|
944
|
+
const defaultReplyHint = replyGuardHint(fBackend.value, fAgentMode.value);
|
|
945
|
+
const classicReplyHint = replyGuardHint(fClassicBackend.value, fAgentMode.value);
|
|
946
|
+
const refreshDefaultReplyHints = () => {
|
|
947
|
+
const fleetSupported = replyGuardSupported(fBackend.value, fAgentMode.value);
|
|
948
|
+
defaultReplyHint.textContent = fleetSupported ? t("replyGuardSupported") : tf("replyGuardUnsupported", fBackend.value, fAgentMode.value);
|
|
949
|
+
const classicSupported = replyGuardSupported(fClassicBackend.value, fAgentMode.value);
|
|
950
|
+
classicReplyHint.textContent = classicSupported ? t("replyGuardSupported") : tf("replyGuardUnsupported", fClassicBackend.value, fAgentMode.value);
|
|
951
|
+
};
|
|
952
|
+
fBackend.addEventListener("change", refreshDefaultReplyHints);
|
|
953
|
+
fClassicBackend.addEventListener("change", refreshDefaultReplyHints);
|
|
954
|
+
fAgentMode.addEventListener("change", refreshDefaultReplyHints);
|
|
892
955
|
const validate = () => {
|
|
893
956
|
const auto = Number(fAutoPause.value), timeout = Number(fHangTimeout.value);
|
|
894
957
|
const concurrency = Number(fConcurrency.value), stagger = Number(fStagger.value);
|
|
@@ -915,6 +978,7 @@
|
|
|
915
978
|
agent_mode: fAgentMode.value,
|
|
916
979
|
tool_set: fToolSet.value,
|
|
917
980
|
tool_progress: fToolProgress.value,
|
|
981
|
+
reply_completion_guard: fReplyGuard.checked,
|
|
918
982
|
log_level: fLogLevel.value,
|
|
919
983
|
hang_detector: { enabled: fHangEnabled.checked, timeout_minutes: Number(fHangTimeout.value) },
|
|
920
984
|
startup: { concurrency: Number(fConcurrency.value), stagger_delay_ms: Number(fStagger.value) },
|
|
@@ -926,21 +990,31 @@
|
|
|
926
990
|
auto_pause_after: d.auto_pause_after ?? 0,
|
|
927
991
|
agent_mode: d.agent_mode || "mcp",
|
|
928
992
|
tool_set: d.tool_set || "full",
|
|
929
|
-
tool_progress: d.tool_progress
|
|
993
|
+
tool_progress: d.tool_progress ?? "off",
|
|
994
|
+
reply_completion_guard: d.reply_completion_guard ?? true,
|
|
930
995
|
log_level: d.log_level || "info",
|
|
931
996
|
hang_detector: { enabled: hang.enabled !== false, timeout_minutes: hang.timeout_minutes ?? 15 },
|
|
932
997
|
startup: { concurrency: startup.concurrency ?? 10, stagger_delay_ms: startup.stagger_delay_ms ?? 500 },
|
|
933
998
|
});
|
|
934
999
|
const classicPatch = changedFields(
|
|
935
|
-
{
|
|
1000
|
+
{
|
|
1001
|
+
backend: fClassicBackend.value,
|
|
1002
|
+
tool_progress: fClassicToolProgress.toggle.checked ? null : fClassicToolProgress.input.value,
|
|
1003
|
+
reply_completion_guard: fClassicReplyGuard.toggle.checked ? null : fClassicReplyGuard.input.checked,
|
|
1004
|
+
admin_users: c.admin_users,
|
|
1005
|
+
allowed_guilds: c.allowed_guilds,
|
|
1006
|
+
},
|
|
936
1007
|
{
|
|
937
1008
|
backend: originalClassicDefaults.backend || d.backend || "claude-code",
|
|
1009
|
+
tool_progress: hasOwn(originalClassicDefaults, "tool_progress") ? originalClassicDefaults.tool_progress : null,
|
|
1010
|
+
reply_completion_guard: hasOwn(originalClassicDefaults, "reply_completion_guard") ? originalClassicDefaults.reply_completion_guard : null,
|
|
938
1011
|
admin_users: originalClassicDefaults.admin_users || [],
|
|
939
1012
|
allowed_guilds: originalClassicDefaults.allowed_guilds || [],
|
|
940
1013
|
},
|
|
941
1014
|
);
|
|
942
1015
|
state.fleet.defaults = { ...d, ...defaultsPatch };
|
|
943
1016
|
state.classic.defaults = { ...c, ...classicPatch };
|
|
1017
|
+
for (const [key, value] of Object.entries(classicPatch)) if (value === null) delete state.classic.defaults[key];
|
|
944
1018
|
if (Object.keys(defaultsPatch).length > 0) {
|
|
945
1019
|
stageChange("defaults:fleet", { label: "Update Agent defaults", impact: Object.keys(defaultsPatch).every(key => HOT_FIELDS.has(key)) ? "now" : "instance", apply: () => api("/api/settings/fleet/defaults", { method: "PUT", body: JSON.stringify(defaultsPatch) }) });
|
|
946
1020
|
}
|
|
@@ -962,7 +1036,8 @@
|
|
|
962
1036
|
}
|
|
963
1037
|
}
|
|
964
1038
|
if (Object.keys(classicPatch).length > 0) {
|
|
965
|
-
|
|
1039
|
+
const classicHotOnly = Object.keys(classicPatch).every(key => key === "tool_progress" || key === "reply_completion_guard");
|
|
1040
|
+
stageChange("defaults:classic", { label: "Update ClassicBot defaults and access", impact: classicHotOnly ? "now" : "fleet", apply: () => api("/api/settings/classic/defaults", { method: "PUT", body: JSON.stringify(classicPatch) }) });
|
|
966
1041
|
}
|
|
967
1042
|
msg.innerHTML = `<span class="s">${esc(t("readyApply"))}</span>`;
|
|
968
1043
|
};
|
|
@@ -978,10 +1053,14 @@
|
|
|
978
1053
|
el("div", { class: "field" }, el("label", {}, t("language"), impact("now")), fLocale),
|
|
979
1054
|
el("div", { class: "field" }, el("label", {}, t("defaultBackend"), impact("instance")), fBackend),
|
|
980
1055
|
el("div", { class: "field" }, el("label", {}, t("defaultModel"), impact("instance")), fModel),
|
|
981
|
-
el("div", { class: "field" }, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("now")), fAutoPause, autoFeedback)
|
|
1056
|
+
el("div", { class: "field" }, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("now")), fAutoPause, autoFeedback),
|
|
1057
|
+
el("div", { class: "field" }, el("label", {}, t("toolProgress"), impact("now")), fToolProgress),
|
|
1058
|
+
el("div", { class: "field" }, el("label", { style: "display:flex;align-items:center;gap:8px" }, fReplyGuard, el("span", {}, t("replyCompletionGuard")), impact("now")), defaultReplyHint))),
|
|
982
1059
|
section("ClassicBot", true,
|
|
983
1060
|
el("div", { class: "grid2" },
|
|
984
|
-
el("div", { class: "field" }, el("label", {}, "Classic default backend", impact("instance")), fClassicBackend)
|
|
1061
|
+
el("div", { class: "field" }, el("label", {}, "Classic default backend", impact("instance")), fClassicBackend),
|
|
1062
|
+
el("div", { class: "field" }, el("label", {}, t("toolProgress"), impact("now")), fClassicToolProgress.row),
|
|
1063
|
+
el("div", { class: "field" }, el("label", {}, t("replyCompletionGuard"), impact("now")), fClassicReplyGuard.row, classicReplyHint)),
|
|
985
1064
|
el("div", { class: "field" }, el("strong", {}, "Who can use ClassicBot"),
|
|
986
1065
|
el("div", { class: "grid2" },
|
|
987
1066
|
el("div", {}, el("label", {}, t("classicAdmins"), impact("fleet")), chipList(c.admin_users, null, "user id")),
|
|
@@ -990,7 +1069,6 @@
|
|
|
990
1069
|
section(t("runtimeResources"), false,
|
|
991
1070
|
el("div", { class: "grid2" },
|
|
992
1071
|
el("div", { class: "field" }, el("label", {}, t("toolSet"), impact("instance")), fToolSet),
|
|
993
|
-
el("div", { class: "field" }, el("label", {}, t("toolProgress"), impact("now")), fToolProgress),
|
|
994
1072
|
el("div", { class: "field" }, el("label", {}, t("logLevel"), impact("now")), fLogLevel),
|
|
995
1073
|
el("div", { class: "field" }, el("label", {}, t("agentMode"), impact("instance")), fAgentMode))),
|
|
996
1074
|
section(t("detection"), false,
|
package/dist/ui/view.html
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
.inst.active { background: rgba(88,166,255,.14); border-left: 3px solid var(--accent); padding-left: 13px; }
|
|
27
27
|
.dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; }
|
|
28
28
|
.dot.running { background: #3fb950; } .dot.stopped { background: #6e7681; } .dot.crashed { background: #f85149; }
|
|
29
|
-
.inst .
|
|
29
|
+
.inst .identity { flex: 1; min-width: 0; }
|
|
30
|
+
.inst .nm { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
31
|
+
.inst .alias { display: block; margin-top: 2px; color: var(--dim); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
30
32
|
.inst .pct { color: var(--dim); font-size: 11px; }
|
|
31
33
|
.cli-icon { width: 10px; height: 10px; flex: 0 0 10px; border-radius: 50%; border: 1px solid rgba(255,255,255,.24); box-shadow: 0 0 0 1px rgba(0,0,0,.18); }
|
|
32
34
|
.cli-claude-code { background: #c678dd; }
|
|
@@ -416,11 +418,9 @@
|
|
|
416
418
|
if (tags.length) return tags[0];
|
|
417
419
|
return "Other";
|
|
418
420
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
function shortName(it) {
|
|
423
|
-
return it.display_name || it.instance_name;
|
|
421
|
+
function sidebarAlias(it) {
|
|
422
|
+
const alias = typeof it.display_name === "string" ? it.display_name.trim() : "";
|
|
423
|
+
return alias && alias !== it.instance_name ? alias : "";
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
const BACKEND_LABELS = {
|
|
@@ -536,7 +536,8 @@
|
|
|
536
536
|
el.className = "inst" + (name === current ? " active" : "");
|
|
537
537
|
el.draggable = true;
|
|
538
538
|
// M2: context_pct != null shows value including 0%; null means unavailable (empty)
|
|
539
|
-
|
|
539
|
+
const alias = sidebarAlias(it);
|
|
540
|
+
el.innerHTML = `<span class="dot ${it.status}"></span><span class="identity"><span class="nm">${esc(it.instance_name)}</span>${alias ? `<span class="alias">${esc(alias)}</span>` : ""}</span><span class="pct">${it.context_pct != null ? Math.round(it.context_pct)+"%" : ""}</span>${backendIconHtml(it.backend)}`;
|
|
540
541
|
el.title = instanceTooltip(it);
|
|
541
542
|
el.onclick = () => select(name);
|
|
542
543
|
wireDrag(el, { type: "instance", name, group: g });
|