mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-21 06:07:13 +08:00
fix(cli): support skill mirror install
This commit is contained in:
@@ -122,7 +122,7 @@ def _clone_repo(git_url: str):
|
|||||||
return tmp_dir, repo_dir
|
return tmp_dir, repo_dir
|
||||||
|
|
||||||
|
|
||||||
def _download_repo_zip(spec: str, branch: str = "main", host: str = "github"):
|
def _download_repo_zip(spec: str, branch: str = "main", host: str = "github", timeout: int = 120):
|
||||||
"""Download a GitHub/GitLab repo as zip and extract it.
|
"""Download a GitHub/GitLab repo as zip and extract it.
|
||||||
|
|
||||||
Returns (tmp_dir, repo_root) where tmp_dir is the temp directory to clean up
|
Returns (tmp_dir, repo_root) where tmp_dir is the temp directory to clean up
|
||||||
@@ -132,7 +132,11 @@ def _download_repo_zip(spec: str, branch: str = "main", host: str = "github"):
|
|||||||
zip_url = f"https://gitlab.com/{spec}/-/archive/{branch}/{spec.split('/')[-1]}-{branch}.zip"
|
zip_url = f"https://gitlab.com/{spec}/-/archive/{branch}/{spec.split('/')[-1]}-{branch}.zip"
|
||||||
else:
|
else:
|
||||||
zip_url = f"https://github.com/{spec}/archive/refs/heads/{branch}.zip"
|
zip_url = f"https://github.com/{spec}/archive/refs/heads/{branch}.zip"
|
||||||
resp = requests.get(zip_url, timeout=120, allow_redirects=True)
|
if isinstance(timeout, (list, tuple)):
|
||||||
|
req_timeout = timeout
|
||||||
|
else:
|
||||||
|
req_timeout = (min(timeout, 5), timeout)
|
||||||
|
resp = requests.get(zip_url, timeout=req_timeout, allow_redirects=True)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
||||||
tmp_dir = tempfile.mkdtemp(prefix="cow-skill-")
|
tmp_dir = tempfile.mkdtemp(prefix="cow-skill-")
|
||||||
@@ -928,13 +932,52 @@ def _install_hub(name, result: InstallResult, provider=None):
|
|||||||
|
|
||||||
if source_type == "github":
|
if source_type == "github":
|
||||||
source_url = data.get("source_url", "")
|
source_url = data.get("source_url", "")
|
||||||
parsed_url = _parse_github_url(source_url)
|
has_mirror = data.get("has_mirror", False)
|
||||||
if parsed_url:
|
gh_err = None
|
||||||
owner, repo, branch, subpath = parsed_url
|
|
||||||
_install_github(f"{owner}/{repo}", result, subpath=subpath, skill_name=name, branch=branch)
|
gh_timeout = 15 if has_mirror else 120
|
||||||
else:
|
try:
|
||||||
_check_github_spec(source_url)
|
parsed_url = _parse_github_url(source_url)
|
||||||
_install_github(source_url, result, skill_name=name)
|
if parsed_url:
|
||||||
|
owner, repo, branch, subpath = parsed_url
|
||||||
|
_install_github(f"{owner}/{repo}", result, subpath=subpath, skill_name=name, branch=branch, timeout=gh_timeout)
|
||||||
|
else:
|
||||||
|
_check_github_spec(source_url)
|
||||||
|
_install_github(source_url, result, skill_name=name, timeout=gh_timeout)
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
gh_err = e
|
||||||
|
if not has_mirror:
|
||||||
|
raise SkillInstallError(f"GitHub download failed: {e}")
|
||||||
|
|
||||||
|
# Fallback: download mirror from Skill Hub
|
||||||
|
result.messages.append(f"GitHub download failed ({gh_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"GitHub download failed ({gh_err}) and mirror also failed: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
|
mirror_ct = mirror_resp.headers.get("Content-Type", "")
|
||||||
|
if "application/zip" not in mirror_ct:
|
||||||
|
raise SkillInstallError(
|
||||||
|
f"GitHub download failed ({gh_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(mirror_resp.content, name, skills_dir, result=result, source_label="cowhub")
|
||||||
|
if len(result.installed) == installed_before:
|
||||||
|
_register_installed_skill(name, source="cowhub")
|
||||||
|
result.installed.append(name)
|
||||||
|
result.messages.append(f"Installed '{name}' from mirror.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if source_type == "registry":
|
if source_type == "registry":
|
||||||
@@ -989,7 +1032,7 @@ def _install_hub(name, result: InstallResult, provider=None):
|
|||||||
raise SkillInstallError("Unexpected response from Skill Hub.")
|
raise SkillInstallError("Unexpected response from Skill Hub.")
|
||||||
|
|
||||||
|
|
||||||
def _install_github(spec, result: InstallResult, subpath=None, skill_name=None, branch="main", source="github"):
|
def _install_github(spec, result: InstallResult, subpath=None, skill_name=None, branch="main", source="github", timeout=120):
|
||||||
"""Install skill(s) from a GitHub repo.
|
"""Install skill(s) from a GitHub repo.
|
||||||
|
|
||||||
Strategy: zip download first (no API rate limit), Contents API as fallback.
|
Strategy: zip download first (no API rate limit), Contents API as fallback.
|
||||||
@@ -1008,7 +1051,7 @@ def _install_github(spec, result: InstallResult, subpath=None, skill_name=None,
|
|||||||
tmp_dir = None
|
tmp_dir = None
|
||||||
repo_root = None
|
repo_root = None
|
||||||
try:
|
try:
|
||||||
tmp_dir, repo_root = _download_repo_zip(spec, branch)
|
tmp_dir, repo_root = _download_repo_zip(spec, branch, timeout=timeout)
|
||||||
except Exception:
|
except Exception:
|
||||||
result.messages.append("Zip download failed, falling back to Contents API...")
|
result.messages.append("Zip download failed, falling back to Contents API...")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user