Polish skill sync controls
This commit is contained in:
@@ -1111,6 +1111,13 @@ function SkillInsertDialog() {
|
||||
const [status, setStatus] = useState("点击后读取当前后端 Skill 列表。");
|
||||
const [updatingSkill, setUpdatingSkill] = useState<string | null>(null);
|
||||
const [syncingSkills, setSyncingSkills] = useState(false);
|
||||
const [bulkUpdatingSkills, setBulkUpdatingSkills] = useState(false);
|
||||
const configurableSkills = skills.filter(
|
||||
(skill) => skill.configurable !== false,
|
||||
);
|
||||
const allSkillsEnabled =
|
||||
configurableSkills.length > 0 &&
|
||||
configurableSkills.every((skill) => skill.enabled !== false);
|
||||
|
||||
async function loadSkills() {
|
||||
setStatus("正在读取 Skill 列表...");
|
||||
@@ -1195,6 +1202,43 @@ function SkillInsertDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
async function setAllSkillsEnabled(enabled: boolean) {
|
||||
if (!configurableSkills.length) return;
|
||||
const previous = skills;
|
||||
setBulkUpdatingSkills(true);
|
||||
setSkills((items) =>
|
||||
items.map((item) =>
|
||||
item.configurable === false ? item : { ...item, enabled },
|
||||
),
|
||||
);
|
||||
try {
|
||||
const response = await fetch("/api/claw/skills", {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ apply_all: true, enabled }),
|
||||
});
|
||||
const payload = (await response.json()) as
|
||||
| SkillSummary[]
|
||||
| { error?: string; detail?: string };
|
||||
if (!response.ok || !Array.isArray(payload)) {
|
||||
throw new Error(
|
||||
Array.isArray(payload)
|
||||
? "更新失败"
|
||||
: (payload.detail ?? payload.error ?? "更新失败"),
|
||||
);
|
||||
}
|
||||
setSkills(payload);
|
||||
setStatus(enabled ? "已启用全部 Skill。" : "已停用全部可选 Skill。");
|
||||
} catch (err) {
|
||||
setSkills(previous);
|
||||
setStatus(err instanceof Error ? err.message : "批量更新 Skill 失败");
|
||||
} finally {
|
||||
setBulkUpdatingSkills(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
@@ -1214,35 +1258,46 @@ function SkillInsertDialog() {
|
||||
<BookOpenIcon className="size-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogContent className="gap-3 p-5">
|
||||
<DialogHeader className="gap-1 pr-6">
|
||||
<DialogTitle>Skills</DialogTitle>
|
||||
<DialogDescription>
|
||||
勾选的 Skill 会进入模型可见列表;点击名称可插入显式调用。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 gap-2"
|
||||
disabled={syncingSkills}
|
||||
onClick={syncSkills}
|
||||
>
|
||||
<RefreshCwIcon
|
||||
className={cn("size-3.5", syncingSkills && "animate-spin")}
|
||||
/>
|
||||
更新 Skill
|
||||
</Button>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
从当前 git 分支拉取最新 skill 文件
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 gap-2 px-2.5"
|
||||
disabled={syncingSkills}
|
||||
onClick={syncSkills}
|
||||
>
|
||||
<RefreshCwIcon
|
||||
className={cn("size-3.5", syncingSkills && "animate-spin")}
|
||||
/>
|
||||
更新 Skill
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2.5"
|
||||
disabled={!configurableSkills.length || bulkUpdatingSkills}
|
||||
onClick={() => setAllSkillsEnabled(!allSkillsEnabled)}
|
||||
>
|
||||
{allSkillsEnabled ? "全取消" : "全选"}
|
||||
</Button>
|
||||
</div>
|
||||
{status ? (
|
||||
<p className="min-w-0 flex-1 truncate text-muted-foreground text-xs">
|
||||
{status}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
{status ? (
|
||||
<p className="text-muted-foreground text-sm">{status}</p>
|
||||
) : null}
|
||||
<div className="grid max-h-96 gap-2 overflow-y-auto">
|
||||
<div className="grid max-h-96 gap-2 overflow-y-auto pt-1">
|
||||
{skills.map((skill) => (
|
||||
<div
|
||||
key={skill.name}
|
||||
|
||||
Reference in New Issue
Block a user