diff --git a/gitea_manager.py b/gitea_manager.py index cfd7752..864d562 100644 --- a/gitea_manager.py +++ b/gitea_manager.py @@ -1,7 +1,7 @@ """ title: Gitea Manager author: Claude -version: 1.2.0 +version: 1.3.0 description: Инструмент для управления Gitea из Open WebUI — создание и удаление репозиториев, организаций, файлов, веток, загрузка и безопасная распаковка ZIP-архивов. requirements: requests """ @@ -70,9 +70,69 @@ class Tools: """Создать репозиторий внутри организации.""" return self._request("POST", f"/orgs/{quote(org, safe='')}/repos", json={"name": name, "description": description, "private": private, "auto_init": auto_init}) - def list_repositories(self) -> str: - """Получить список репозиториев текущего пользователя.""" - return self._request("GET", "/user/repos") + def list_repositories( + self, + limit: int = 50, + page: int = 1, + sort: str = "updated", + fields: Optional[str] = "name,private,language,html_url,description,updated_at,default_branch", + ) -> str: + """ + Получить список репозиториев текущего пользователя в компактном виде. + + По умолчанию возвращает не весь JSON Gitea, а только краткий набор полей — + иначе ответ раздувается из-за permissions/url/настроек и обрезается в чате. + Если репозиториев больше, чем limit, в конце добавляется подсказка про page+1. + + Args: + limit: максимум репозиториев на странице (1..100). + page: номер страницы (начиная с 1). + sort: сортировка — updated | created | alpha | size | id. + fields: список полей через запятую, которые нужно оставить. + Пустая строка — вернуть весь JSON как есть. + """ + safe_limit = max(1, min(int(limit or 50), 100)) + safe_page = max(1, int(page or 1)) + allowed_sort = {"updated", "created", "alpha", "size", "id"} + safe_sort = sort if sort in allowed_sort else "updated" + + raw = self._request( + "GET", + "/user/repos", + params={"limit": safe_limit, "page": safe_page, "sort": safe_sort}, + ) + + # Если Gitea вернула ошибку — _request отдаёт строку "Ошибка ...". + # Парсить как JSON нечего — возвращаем как есть. + if not raw or not raw.lstrip().startswith("["): + return raw + + try: + repos = json.loads(raw) + except (ValueError, TypeError): + return raw + + if not isinstance(repos, list): + return raw + + # Пустой fields — режим «как раньше», отдаём весь JSON. + if not fields: + return raw + + keep = {f.strip() for f in fields.split(",") if f.strip()} + compact = [ + {k: r.get(k) for k in keep if isinstance(r, dict) and k in r} + for r in repos + if isinstance(r, dict) + ] + + hint = "" + if len(repos) >= safe_limit: + hint = ( + f"\n\n[Есть ещё репозитории — вызови " + f"list_repositories(limit={safe_limit}, page={safe_page + 1})]" + ) + return json.dumps(compact, ensure_ascii=False, indent=2) + hint def get_repository_info(self, owner: str, repo: str) -> str: """Получить информацию о репозитории.""" @@ -273,4 +333,4 @@ class Tools: else: if target.exists(): target.unlink() - shutil.move(str(item), str(target)) + shutil.move(str(item), str(target)) \ No newline at end of file