- _do_upload_skill 在解析出技能名后,若 zip 内 frontmatter name 对应一个已存在的技能目录,
则安装到该目录(覆盖)而非新建,修复“更新后列表出现两个同名技能”的问题
else:
fallback = (body.get("filename") or "skill").rsplit(".", 1)[0]
name = fallback
+ # 防重复:若 zip 内声明的 skill 名对应一个已存在的技能目录,则覆盖该目录,
+ # 而不是新建一个(避免“更新/上传”后列表出现两个同名技能)。
+ zf_fm = _skill_name_from_zip(zf)
+ if zf_fm:
+ existing = SKILLS_ROOT / zf_fm
+ if existing.exists() and existing.resolve() != (SKILLS_ROOT / name).resolve():
+ name = zf_fm
if not _NAME_RE.match(name):
zf.close()
return JSONResponse({"error": f"skill 名称非法: {name}(仅允许字母数字 - _,长度 1-64)"}, status_code=400)