#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Soul 运营全链路技能包:将 SKILL + 脚本 + Cursor 入口打成 zip,默认输出到用户「下载」文件夹。 用法: python3 scripts/pack_soul_operation_skills.py """ from __future__ import annotations import shutil import sys import zipfile from pathlib import Path STAMP = "20260320" BUNDLE_TOP = f"Soul运营全链路技能包_{STAMP}" # 卡若AI 根目录(按你本机实际修改) KARUO_AI = Path("/Users/karuo/Documents/个人/卡若AI") CURSOR_SKILLS = Path.home() / ".cursor" / "skills" DOWNLOADS = Path.home() / "Downloads" # 在永平项目下临时组装(本仓库内,便于工具写入) REPO_ROOT = Path(__file__).resolve().parents[1] STAGING_PARENT = REPO_ROOT / ".tmp_skill_bundle" STAGING = STAGING_PARENT / BUNDLE_TOP def ignore_copy(dirpath: str, names: list[str]) -> list[str]: """排除缓存、浏览器运行时目录(含断链/套接字,会导致 copytree 失败)。""" skip_dirs = {"__pycache__", ".browser_state", "chromium_data"} skip_files = {".DS_Store"} ignored: list[str] = [] for n in names: if n in skip_dirs or n in skip_files or n.endswith(".pyc"): ignored.append(n) return ignored def copytree(src: Path, dst: Path) -> None: if not src.exists(): print(f"SKIP 不存在: {src}", file=sys.stderr) return dst.parent.mkdir(parents=True, exist_ok=True) shutil.copytree(src, dst, dirs_exist_ok=True, ignore=ignore_copy) def main() -> int: if not KARUO_AI.is_dir(): print(f"ERROR: 未找到卡若AI目录: {KARUO_AI}", file=sys.stderr) return 1 if STAGING.exists(): shutil.rmtree(STAGING) STAGING.mkdir(parents=True) # Cursor 入口 csk = STAGING / ".cursor" / "skills" csk.mkdir(parents=True, exist_ok=True) for name in ("soul-operation-report", "soul-party-project"): p = CURSOR_SKILLS / name if p.is_dir(): copytree(p, csk / name) kai = STAGING / "卡若AI" copytree( KARUO_AI / "02_卡人(水)" / "水岸_项目管理", kai / "02_卡人(水)" / "水岸_项目管理", ) bridge = KARUO_AI / "02_卡人(水)" / "水桥_平台对接" for sub in ("飞书管理", "智能纪要", "Soul创业实验"): copytree(bridge / sub, kai / "02_卡人(水)" / "水桥_平台对接" / sub) wood = KARUO_AI / "03_卡木(木)" / "木叶_视频内容" wdst = kai / "03_卡木(木)" / "木叶_视频内容" for sub in ( "视频切片", "多平台分发", "抖音发布", "B站发布", "视频号发布", "小红书发布", "快手发布", ): copytree(wood / sub, wdst / sub) idx = KARUO_AI / "运营中枢" / "工作台" / "00_账号与API索引.md" if idx.is_file(): (kai / "运营中枢" / "工作台").mkdir(parents=True, exist_ok=True) shutil.copy2(idx, kai / "运营中枢" / "工作台" / idx.name) readme = STAGING / "解压后必读.md" readme.write_text( """# Soul 运营全链路技能包 ## 包含内容 - `.cursor/skills/`:`soul-operation-report`、`soul-party-project` - `卡若AI/02_卡人(水)/水岸_项目管理/` - `卡若AI/02_卡人(水)/水桥_平台对接/飞书管理/`、`智能纪要/`、`Soul创业实验/` - `卡若AI/03_卡木(木)/木叶_视频内容/`:视频切片、多平台分发、各平台发布 - `卡若AI/运营中枢/工作台/00_账号与API索引.md`(若源机存在) ## 另一台电脑怎么用 1. 解压后,将 `卡若AI/` **合并**到你本机卡若AI根目录(先备份)。 2. 将 `.cursor/skills/` 下两个目录复制到 `~/.cursor/skills/`。 3. 安装 Python/FFmpeg/conda 等依赖,按各 SKILL 与 `Soul创业实验/上传/环境与TOKEN配置.md` 配置 Token、Cookie、永平项目 `.env`。 4. 文档或脚本里的 `/Users/karuo/...` 需改成本机路径。 **安全**:包内可能有凭证说明,勿上传公开网盘。 """, encoding="utf-8", ) for p in list(STAGING.rglob("__pycache__")): if p.is_dir(): shutil.rmtree(p, ignore_errors=True) for p in STAGING.rglob("*.pyc"): try: p.unlink() except OSError: pass DOWNLOADS.mkdir(parents=True, exist_ok=True) zip_path = DOWNLOADS / f"{BUNDLE_TOP}.zip" with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: for f in STAGING.rglob("*"): if f.is_file(): arcname = Path(BUNDLE_TOP) / f.relative_to(STAGING) zf.write(f, arcname.as_posix()) mb = zip_path.stat().st_size / (1024 * 1024) print(f"完成: {zip_path} ({mb:.2f} MB)") print(f"临时目录(可删): {STAGING}") return 0 if __name__ == "__main__": raise SystemExit(main())