diff --git a/README.md b/README.md index 426914b..d5e0031 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,14 @@ git clone https://github.com/perkfly/ex-skill ~/.claude/skills/create-ex git clone https://github.com/perkfly/ex-skill ~/.openclaw/workspace/skills/create-ex ``` -### 依赖(可选) +### 依赖 ```bash pip3 install -r requirements.txt ``` +> ⚠️ 使用**中文昵称**时 `pypinyin` 为必需依赖:未安装时无法从中文昵称生成 slug,工具会明确报错并提示。仅使用英文昵称可跳过安装。 + --- ## 使用 diff --git a/README_EN.md b/README_EN.md index ffe94ea..02fa117 100644 --- a/README_EN.md +++ b/README_EN.md @@ -60,12 +60,14 @@ git clone https://github.com/perkfly/ex-skill .claude/skills/create-ex git clone https://github.com/perkfly/ex-skill ~/.claude/skills/create-ex ``` -### Dependencies (optional) +### Dependencies ```bash pip3 install -r requirements.txt ``` +> ⚠️ `pypinyin` is **required for Chinese nicknames** — without it no slug can be generated from a Chinese name (the tool fails with a clear error instead of silently colliding). Optional if you only use ASCII nicknames. + --- ## Usage diff --git a/SKILL.md b/SKILL.md index fc1755f..9a7bcdc 100644 --- a/SKILL.md +++ b/SKILL.md @@ -210,6 +210,8 @@ Persona 摘要: 用户确认后,执行以下写入操作: +**0. 检查 slug 冲突**:若 `exes/{slug}` 目录已存在,**停止写入**,询问用户是换一个 slug 还是确认覆盖(覆盖前先用 `version_manager.py --action backup` 存档)。不要静默覆盖已有前任的数据。 + **1. 创建目录结构**(用 Bash): ```bash mkdir -p exes/{slug}/versions @@ -551,6 +553,8 @@ Confirm generation? Or need adjustments? After user confirmation, execute the following: +**0. Check for slug collision**: if `exes/{slug}` already exists, **stop** and ask the user to pick a different slug or explicitly confirm overwriting (archive first via `version_manager.py --action backup`). Never silently overwrite an existing ex. + **1. Create directory structure** (Bash): ```bash mkdir -p exes/{slug}/versions diff --git a/requirements.txt b/requirements.txt index 152b59c..5ca81dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ -# Optional: Chinese name → slug conversion +# Required for Chinese nicknames (slug generation); optional for ASCII-only names +# 中文昵称必需(用于生成 slug);纯英文昵称可不装 pypinyin>=0.48.0 # Optional: Better EXIF support for more image formats (HEIC, TIFF, etc.) diff --git a/tools/skill_writer.py b/tools/skill_writer.py index 6bcad94..7b26110 100644 --- a/tools/skill_writer.py +++ b/tools/skill_writer.py @@ -69,6 +69,8 @@ def slugify(name: str) -> str: """ 将姓名转为 slug。 优先尝试 pypinyin(如已安装),否则 fallback 到简单处理。 + 无法生成有效 slug 时返回空字符串(例如:中文昵称 + 未安装 pypinyin), + 由调用方决定如何处理,避免不同昵称静默撞车。 """ try: from pypinyin import lazy_pinyin @@ -86,7 +88,7 @@ def slugify(name: str) -> str: import re slug = re.sub(r"_+", "_", slug).strip("_") - return slug if slug else "ex" + return slug def build_identity_string(meta: dict) -> str: @@ -125,9 +127,14 @@ def create_skill( memories_content: str, persona_content: str, ) -> Path: - """创建新的前任 Skill 目录结构""" + """创建新的前任 Skill 目录结构。目标目录已存在时抛出 FileExistsError,防止静默覆盖。""" skill_dir = base_dir / slug + if skill_dir.exists(): + raise FileExistsError( + f"{skill_dir} 已存在。请换一个 slug," + f"或先用 version_manager.py 存档/手动备份后再删除,避免静默覆盖导致数据丢失" + ) skill_dir.mkdir(parents=True, exist_ok=True) # 创建子目录 @@ -343,7 +350,14 @@ def main() -> None: if args.name: meta["name"] = args.name - slug = args.slug or slugify(meta.get("name", "ex")) + slug = args.slug or slugify(meta.get("name", "")) + if not slug: + print( + "错误:无法从昵称生成 slug(中文昵称需要安装 pypinyin:pip3 install pypinyin)," + "或请显式传入 --slug", + file=sys.stderr, + ) + sys.exit(1) memories_content = "" if args.memories: @@ -353,7 +367,11 @@ def main() -> None: if args.persona: persona_content = Path(args.persona).read_text(encoding="utf-8") - skill_dir = create_skill(base_dir, slug, meta, memories_content, persona_content) + try: + skill_dir = create_skill(base_dir, slug, meta, memories_content, persona_content) + except FileExistsError as e: + print(f"错误:{e}", file=sys.stderr) + sys.exit(1) print(f"✅ Skill 已创建:{skill_dir}") print(f" 触发词:/{slug}")