From a0c90edf48a1f8e6bf8a08823fedc680e5d89663 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Sat, 4 Jul 2026 15:15:31 -0700 Subject: [PATCH] fix(skills): retry rate-limited Contents API directory listings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Contents-API fallback's directory listing used a raw httpx.get with no retry, so a 429/403 rate limit aborted the whole skill download even though file fetches already retry via _github_get. Route the directory listing through the same helper (429/reset-aware backoff, 5xx retry, rate-limit flagging). Salvage of PR #3033's intent — rerouted through the _github_get helper that landed after the PR was opened, instead of the PR's ad-hoc retry loops. Co-authored-by: 0xbyt4 <35742124+0xbyt4@users.noreply.github.com> --- tools/skills_hub.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/skills_hub.py b/tools/skills_hub.py index d8408173183..db169b37d6d 100644 --- a/tools/skills_hub.py +++ b/tools/skills_hub.py @@ -909,12 +909,13 @@ class GitHubSource(SkillSource): def _download_directory_recursive(self, repo: str, path: str) -> Dict[str, str]: """Recursively download via Contents API (fallback).""" url = f"https://api.github.com/repos/{repo}/contents/{path.rstrip('/')}" - try: - resp = httpx.get(url, headers=self.auth.get_headers(), timeout=15, follow_redirects=True) - if resp.status_code != 200: - logger.debug("Contents API returned %d for %s/%s", resp.status_code, repo, path) - return {} - except httpx.HTTPError: + # Route through _github_get so directory listing gets the same + # 429/403-rate-limit retry + backoff as file fetches (#3033). + resp = self._github_get(url) + if resp is None: + return {} + if resp.status_code != 200: + logger.debug("Contents API returned %d for %s/%s", resp.status_code, repo, path) return {} entries = resp.json()