mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-20 02:17:24 +00:00
fix(skills): fix dep detection false positives and all-or-nothing install
- Filter Python stdlib modules at scan time to prevent false positives when the runtime checker fails (e.g. pip:argparse, pip:sys) - Install pip/npm packages one-by-one instead of batch so partial success is preserved when one package fails - Persist missing deps to DB after install via StoreMissingDeps() so reload reflects actual state instead of stale data - Use explicit master tenant context in handleInstallDeps for consistency with rescanAndUpdate()
This commit is contained in:
1 parent
ecf6463d98
commit
899c8eb0b4
5 files changed
+330
-25
No files matched your search
+26
-10
@@ -255,7 +255,11 @@ func (h *SkillsHandler) handleInstallDeps(w http.ResponseWriter, r *http.Request
|
||||
if !h.requireMasterTenant(w, r) {
|
||||
return
|
||||
}
|
||||
dirs := h.skills.ListSystemSkillDirs(r.Context())
|
||||
// Use explicit master tenant context for system skill operations,
|
||||
// consistent with rescanAndUpdate() pattern.
|
||||
masterCtx := store.WithTenantID(r.Context(), store.MasterTenantID)
|
||||
|
||||
dirs := h.skills.ListSystemSkillDirs(masterCtx)
|
||||
if len(dirs) == 0 {
|
||||
writeJSON(w, http.StatusOK, map[string]string{"message": "no system skills"})
|
||||
return
|
||||
@@ -274,25 +278,24 @@ func (h *SkillsHandler) handleInstallDeps(w http.ResponseWriter, r *http.Request
|
||||
})
|
||||
}
|
||||
|
||||
result, err := installManagedDeps(r.Context(), manifest, missing)
|
||||
result, err := installManagedDeps(masterCtx, manifest, missing)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Re-check all system skills and update status after install
|
||||
allSkills := h.skills.ListAllSkills(r.Context())
|
||||
// Re-check all system skills, persist missing deps, and update status.
|
||||
allSkills := h.skills.ListAllSkills(masterCtx)
|
||||
statusChanged := false
|
||||
for _, sk := range allSkills {
|
||||
if !sk.IsSystem {
|
||||
continue
|
||||
}
|
||||
dir, exists := dirs[sk.Slug]
|
||||
if !exists {
|
||||
if _, exists := dirs[sk.Slug]; !exists {
|
||||
continue
|
||||
}
|
||||
m := h.scanWithFallback(sk)
|
||||
if m == nil || m.IsEmpty() {
|
||||
_ = dir // dir was used for direct scan; fallback uses sk.BaseDir
|
||||
continue
|
||||
}
|
||||
ok, miss := skills.CheckSkillDeps(m)
|
||||
@@ -300,10 +303,20 @@ func (h *SkillsHandler) handleInstallDeps(w http.ResponseWriter, r *http.Request
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ok && sk.Status == "archived" {
|
||||
_ = h.skills.UpdateSkill(r.Context(), id, map[string]any{"status": "active"})
|
||||
h.skills.BumpVersion()
|
||||
|
||||
// Persist actual missing deps to DB so reload reflects reality.
|
||||
_ = h.skills.StoreMissingDeps(masterCtx, id, miss)
|
||||
|
||||
// Update status in both directions.
|
||||
switch {
|
||||
case ok && sk.Status == "archived":
|
||||
_ = h.skills.UpdateSkill(masterCtx, id, map[string]any{"status": "active"})
|
||||
statusChanged = true
|
||||
case !ok && sk.Status != "archived":
|
||||
_ = h.skills.UpdateSkill(masterCtx, id, map[string]any{"status": "archived"})
|
||||
statusChanged = true
|
||||
}
|
||||
|
||||
status := "active"
|
||||
if !ok {
|
||||
status = "archived"
|
||||
@@ -319,6 +332,9 @@ func (h *SkillsHandler) handleInstallDeps(w http.ResponseWriter, r *http.Request
|
||||
})
|
||||
}
|
||||
}
|
||||
if statusChanged {
|
||||
h.skills.BumpVersion()
|
||||
}
|
||||
|
||||
if h.msgBus != nil {
|
||||
h.msgBus.Broadcast(bus.Event{
|
||||
|
||||
Reference in new issue
Block a user