Skip to content

Commit 4bab09a

Browse files
committed
refactor: improve failed plugin diagnostics and uninstall flow
1 parent 26e68ed commit 4bab09a

2 files changed

Lines changed: 90 additions & 63 deletions

File tree

astrbot/core/star/star_manager.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,19 @@ def _rebuild_failed_plugin_info(self) -> None:
461461
for dir_name, info in self.failed_plugin_dict.items():
462462
if isinstance(info, dict):
463463
error = info.get("error", "未知错误")
464+
display_name = info.get("display_name") or info.get("name") or dir_name
465+
version = info.get("version") or info.get("astrbot_version")
466+
if version:
467+
lines.append(
468+
f"加载插件「{display_name}」(目录: {dir_name}, 版本: {version}) 时出现问题,原因:{error}。",
469+
)
470+
else:
471+
lines.append(
472+
f"加载插件「{display_name}」(目录: {dir_name}) 时出现问题,原因:{error}。",
473+
)
464474
else:
465475
error = str(info)
466-
lines.append(f"加载 {dir_name} 插件时出现问题,原因 {error}。")
476+
lines.append(f"加载插件目录 {dir_name} 时出现问题,原因{error}。")
467477

468478
self.failed_plugin_info = "\n".join(lines) + "\n"
469479

dashboard/src/views/extension/useExtensionPage.js

Lines changed: 79 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -509,90 +509,113 @@ export const useExtensionPage = () => {
509509
}
510510
};
511511

512+
const showReloadFeedback = (message, type) => {
513+
clearReloadFeedback();
514+
setReloadFeedback(message, type);
515+
toast(message, type === "success" ? "success" : "error");
516+
};
517+
512518
const reloadFailedPlugin = async (dirName) => {
513-
// Reset stale inline feedback before each retry attempt
519+
if (!dirName) return;
514520
clearReloadFeedback();
515521

516-
if (!dirName) {
517-
return;
518-
}
519522
try {
520523
const res = await axios.post("/api/plugin/reload-failed", { dir_name: dirName });
521524
if (res.data.status === "error") {
522-
const message = res.data.message || tm("messages.reloadFailed");
523-
setReloadFeedback(message, "error");
524-
toast(message, "error");
525+
showReloadFeedback(res.data.message || tm("messages.reloadFailed"), "error");
525526
return;
526527
}
527-
setReloadFeedback(res.data.message || tm("messages.reloadSuccess"), "success");
528+
showReloadFeedback(res.data.message || tm("messages.reloadSuccess"), "success");
528529
await getExtensions();
529530
} catch (err) {
530-
const message = resolveErrorMessage(err, tm("messages.reloadFailed"));
531-
setReloadFeedback(message, "error");
532-
toast(message, "error");
531+
showReloadFeedback(
532+
resolveErrorMessage(err, tm("messages.reloadFailed")),
533+
"error",
534+
);
533535
}
534536
};
535537

536-
const requestUninstall = (kind, id) => {
537-
if (!id) return;
538-
uninstallTarget.value = { kind, id };
538+
const openUninstallDialog = (target) => {
539+
if (!target?.id) return;
540+
uninstallTarget.value = target;
539541
showUninstallDialog.value = true;
540542
};
541543

542-
const requestUninstallPlugin = (name) => {
543-
requestUninstall("normal", name);
544-
};
545-
546-
const requestUninstallFailedPlugin = (dirName) => {
547-
requestUninstall("failed", dirName);
548-
};
549-
550-
const performUninstall = async (target, options = {}) => {
551-
if (!target?.id) return;
552-
553-
const { deleteConfig = false, deleteData = false } = options || {};
554-
toast(`${tm("messages.uninstalling")} ${target.id}`, "primary");
555-
544+
const doUninstallNormal = async (
545+
name,
546+
{ deleteConfig = false, deleteData = false } = {},
547+
) => {
548+
toast(`${tm("messages.uninstalling")} ${name}`, "primary");
556549
try {
557-
if (target.kind === "failed") {
558-
const res = await axios.post("/api/plugin/uninstall-failed", {
559-
dir_name: target.id,
560-
delete_config: deleteConfig,
561-
delete_data: deleteData,
562-
});
563-
if (res.data.status === "error") {
564-
toast(res.data.message, "error");
565-
return;
566-
}
567-
toast(res.data.message, "success");
568-
await getExtensions();
550+
const res = await axios.post("/api/plugin/uninstall", {
551+
name,
552+
delete_config: deleteConfig,
553+
delete_data: deleteData,
554+
});
555+
if (res.data.status === "error") {
556+
toast(res.data.message, "error");
569557
return;
570558
}
559+
Object.assign(extension_data, res.data);
560+
toast(res.data.message, "success");
561+
await getExtensions();
562+
} catch (err) {
563+
toast(resolveErrorMessage(err), "error");
564+
}
565+
};
571566

572-
const res = await axios.post("/api/plugin/uninstall", {
573-
name: target.id,
567+
const doUninstallFailed = async (
568+
dirName,
569+
{ deleteConfig = false, deleteData = false } = {},
570+
) => {
571+
toast(`${tm("messages.uninstalling")} ${dirName}`, "primary");
572+
try {
573+
const res = await axios.post("/api/plugin/uninstall-failed", {
574+
dir_name: dirName,
574575
delete_config: deleteConfig,
575576
delete_data: deleteData,
576577
});
577578
if (res.data.status === "error") {
578579
toast(res.data.message, "error");
579580
return;
580581
}
581-
Object.assign(extension_data, res.data);
582582
toast(res.data.message, "success");
583583
await getExtensions();
584584
} catch (err) {
585585
toast(resolveErrorMessage(err), "error");
586586
}
587587
};
588588

589-
const uninstallFailedPlugin = async (dirName, options = null) => {
589+
const uninstallNormalPlugin = async (
590+
name,
591+
{ skipConfirm = false, ...options } = {},
592+
) => {
593+
if (!name) return;
594+
if (!skipConfirm) {
595+
openUninstallDialog({ kind: "normal", id: name });
596+
return;
597+
}
598+
await doUninstallNormal(name, options);
599+
};
600+
601+
const uninstallFailedPlugin = async (
602+
dirName,
603+
{ skipConfirm = false, ...options } = {},
604+
) => {
590605
if (!dirName) return;
591-
if (!options || typeof options !== "object") {
592-
requestUninstallFailedPlugin(dirName);
606+
if (!skipConfirm) {
607+
openUninstallDialog({ kind: "failed", id: dirName });
593608
return;
594609
}
595-
await performUninstall({ kind: "failed", id: dirName }, options);
610+
await doUninstallFailed(dirName, options);
611+
};
612+
613+
const requestUninstallPlugin = (name) => {
614+
uninstallNormalPlugin(name);
615+
};
616+
617+
const requestUninstallFailedPlugin = (dirName) => {
618+
uninstallFailedPlugin(dirName);
596619
};
597620

598621
const checkUpdate = () => {
@@ -624,23 +647,13 @@ export const useExtensionPage = () => {
624647
});
625648
};
626649

627-
const uninstallExtension = async (extensionName, optionsOrSkipConfirm = false) => {
650+
const uninstallExtension = async (extensionName, options = null) => {
628651
if (!extensionName) return;
629-
630-
if (typeof optionsOrSkipConfirm === "boolean") {
631-
if (!optionsOrSkipConfirm) {
632-
requestUninstallPlugin(extensionName);
633-
return;
634-
}
635-
await performUninstall({ kind: "normal", id: extensionName });
652+
if (options && typeof options === "object") {
653+
await uninstallNormalPlugin(extensionName, { ...options, skipConfirm: true });
636654
return;
637655
}
638-
639-
const options =
640-
typeof optionsOrSkipConfirm === "object" && optionsOrSkipConfirm !== null
641-
? optionsOrSkipConfirm
642-
: {};
643-
await performUninstall({ kind: "normal", id: extensionName }, options);
656+
await uninstallNormalPlugin(extensionName);
644657
};
645658

646659
// 处理卸载确认对话框的确认事件
@@ -649,7 +662,11 @@ export const useExtensionPage = () => {
649662
if (!target) return;
650663

651664
try {
652-
await performUninstall(target, options);
665+
if (target.kind === "normal") {
666+
await doUninstallNormal(target.id, options);
667+
} else {
668+
await doUninstallFailed(target.id, options);
669+
}
653670
} finally {
654671
uninstallTarget.value = null;
655672
showUninstallDialog.value = false;

0 commit comments

Comments
 (0)