From 00353dd0cb874b0795049bff21898551ff5848c3 Mon Sep 17 00:00:00 2001 From: zhayujie Date: Mon, 30 Mar 2026 18:46:02 +0800 Subject: [PATCH] feat: support skill hub mirror --- cli/commands/skill.py | 67 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/cli/commands/skill.py b/cli/commands/skill.py index 43c47dcb..891bceca 100644 --- a/cli/commands/skill.py +++ b/cli/commands/skill.py @@ -548,14 +548,26 @@ def _check_github_spec(spec: str): raise SkillInstallError(f"Invalid GitHub spec '{spec}'. Expected format: owner/repo") +_JUNK_NAMES = {'.DS_Store', 'Thumbs.db', 'desktop.ini'} + + +def _is_junk_entry(filename: str) -> bool: + parts = filename.replace('\\', '/').split('/') + return any(p in _JUNK_NAMES or p == '__MACOSX' or p.startswith('._.') for p in parts) + + def _safe_extractall(zf: zipfile.ZipFile, dest: str): - """Extract zip while guarding against Zip Slip (path traversal).""" + """Extract zip while guarding against Zip Slip and filtering junk files.""" dest = os.path.realpath(dest) + members = [] for member in zf.infolist(): + if _is_junk_entry(member.filename): + continue target = os.path.realpath(os.path.join(dest, member.filename)) if not target.startswith(dest + os.sep) and target != dest: raise ValueError(f"Unsafe zip entry detected: {member.filename}") - zf.extractall(dest) + members.append(member) + zf.extractall(dest, members=members) def _verify_checksum(content: bytes, expected: str): @@ -987,21 +999,60 @@ def _install_hub(name, result: InstallResult, provider=None): if parsed.scheme != "https": raise SkillInstallError("Refusing to download from non-HTTPS URL.") src_provider = data.get("source_provider", "registry") + has_mirror = data.get("has_mirror", False) expected_checksum = data.get("checksum") or data.get("sha256") result.messages.append(f"Source: {src_provider}") result.messages.append("Downloading skill package...") + dl_err = None + dl_timeout = 15 if has_mirror else 60 try: - dl_resp = requests.get(download_url, timeout=60, allow_redirects=True) + dl_resp = requests.get( + download_url, + timeout=(min(dl_timeout, 5), dl_timeout), + allow_redirects=True, + ) dl_resp.raise_for_status() except Exception as e: - raise SkillInstallError(f"Failed to download from {src_provider}: {e}") - _check_checksum(dl_resp.content, expected_checksum) + dl_err = e + if not has_mirror: + raise SkillInstallError(f"Failed to download from {src_provider}: {e}") + + if dl_err is None: + _check_checksum(dl_resp.content, expected_checksum) + installed_before = len(result.installed) + _install_zip_bytes(dl_resp.content, name, skills_dir, result=result, source_label=src_provider) + if len(result.installed) == installed_before: + _register_installed_skill(name, source=src_provider) + result.installed.append(name) + result.messages.append(f"Installed '{name}' from {src_provider}.") + return + + # Fallback: download mirror from Skill Hub + result.messages.append(f"Direct download failed ({dl_err}), trying mirror...") + try: + mirror_resp = requests.post( + f"{SKILL_HUB_API}/skills/{name}/download", + json={"mirror": True}, + timeout=60, + ) + mirror_resp.raise_for_status() + except Exception as e: + raise SkillInstallError( + f"Direct download failed ({dl_err}) and mirror also failed: {e}" + ) + mirror_ct = mirror_resp.headers.get("Content-Type", "") + if "application/zip" not in mirror_ct: + raise SkillInstallError( + f"Direct download failed ({dl_err}) and mirror returned unexpected content." + ) + expected_checksum = mirror_resp.headers.get("X-Checksum-Sha256") + _check_checksum(mirror_resp.content, expected_checksum) installed_before = len(result.installed) - _install_zip_bytes(dl_resp.content, name, skills_dir, result=result, source_label=src_provider) + _install_zip_bytes(mirror_resp.content, name, skills_dir, result=result, source_label="cowhub") if len(result.installed) == installed_before: - _register_installed_skill(name, source=src_provider) + _register_installed_skill(name, source="cowhub") result.installed.append(name) - result.messages.append(f"Installed '{name}' from {src_provider}.") + result.messages.append(f"Installed '{name}' from mirror.") else: raise SkillInstallError("Unsupported registry provider.") return