diff --git a/pkg/nodes/registry_server.go b/pkg/nodes/registry_server.go index d01eb70..b0b6dc4 100644 --- a/pkg/nodes/registry_server.go +++ b/pkg/nodes/registry_server.go @@ -916,7 +916,18 @@ func (s *RegistryServer) handleWebUISkills(w http.ResponseWriter, r *http.Reques http.Error(w, "clawhub is not installed. please install clawhub first.", http.StatusPreconditionFailed) return } - cmd := exec.CommandContext(r.Context(), clawhubPath, "install", name) + ignoreSuspicious := false + switch v := body["ignore_suspicious"].(type) { + case bool: + ignoreSuspicious = v + case string: + ignoreSuspicious = strings.EqualFold(strings.TrimSpace(v), "true") || strings.TrimSpace(v) == "1" + } + args := []string{"install", name} + if ignoreSuspicious { + args = append(args, "--force") + } + cmd := exec.CommandContext(r.Context(), clawhubPath, args...) cmd.Dir = strings.TrimSpace(s.workspacePath) out, err := cmd.CombinedOutput() if err != nil { diff --git a/webui/src/i18n/index.ts b/webui/src/i18n/index.ts index c87434a..de4ee38 100644 --- a/webui/src/i18n/index.ts +++ b/webui/src/i18n/index.ts @@ -189,6 +189,7 @@ const resources = { skillsImportDoneMessage: 'Skill imported successfully.', skillsFileSaved: 'Skill file saved successfully.', skillsNamePlaceholder: 'skill name', + skillsIgnoreSuspicious: 'Ignore suspicious warning (use --force)', skillsClawhubNotFound: 'clawhub not found', skillsClawhubStatus: 'clawhub', skillsAdd: 'Add Skill', @@ -491,6 +492,7 @@ const resources = { skillsImportDoneMessage: '技能导入成功。', skillsFileSaved: '技能文件保存成功。', skillsNamePlaceholder: '技能名', + skillsIgnoreSuspicious: '忽略可疑告警(使用 --force)', skillsClawhubNotFound: '未找到 clawhub', skillsClawhubStatus: 'clawhub', skillsAdd: '添加技能', diff --git a/webui/src/pages/Skills.tsx b/webui/src/pages/Skills.tsx index 82fbb3c..06846fc 100644 --- a/webui/src/pages/Skills.tsx +++ b/webui/src/pages/Skills.tsx @@ -11,6 +11,7 @@ const Skills: React.FC = () => { const ui = useUI(); const [installName, setInstallName] = useState(''); const [installingSkill, setInstallingSkill] = useState(false); + const [ignoreSuspicious, setIgnoreSuspicious] = useState(false); const qp = (k: string, v: string) => `${q}${q ? '&' : '?'}${k}=${encodeURIComponent(v)}`; const [isFileModalOpen, setIsFileModalOpen] = useState(false); @@ -76,7 +77,7 @@ const Skills: React.FC = () => { const r = await fetch(`/webui/api/skills${q}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ action: 'install', name }), + body: JSON.stringify({ action: 'install', name, ignore_suspicious: ignoreSuspicious }), }); if (!r.ok) { ui.hideLoading(); @@ -190,6 +191,15 @@ const Skills: React.FC = () => {
setInstallName(e.target.value)} placeholder={t('skillsNamePlaceholder')} className="px-3 py-2 bg-zinc-950 border border-zinc-800 rounded-lg text-sm disabled:opacity-60" /> +