developer-tools
claude-api-guard ловит ломающие изменения API в CI
Claude News
developer-toolsclaude-api-guard проверяет на каждом pull request, не сломались ли вызовы Claude и OpenAI API из-за уже объявленных изменений провайдеров, и 5 правил из примерно 19 применяет к коду сам. Инструмент и подробный инженерный журнал опубликованы на Github под лицензией Business Source License 1.1, которая 1 сентября 2030 года автоматически станет MIT.
Коротко
- Проверка подключается как GitHub Action без ключей и конфигов, роняет сборку только на находках уровня HIGH, а правила лежат в репозитории и при сканировании не обращаются к модели.
- Разбор синтаксического дерева вместо текста файла и два структурных условия снизили находки в litellm с 1 720 до 2, а первая версия на регулярных выражениях давала 1 576 находок по шести репозиториям.
- Набор правил обновляется еженедельным заданием, которое читает release notes Anthropic и OpenAI, извлекает ломающие изменения через LLM и выносит каждое новое правило в PR на ручную проверку.
Ценность такого инструмента определяется долей ложных срабатываний: сканер, который выдаёт на большом репозитории тысячу находок, перестают открывать через неделю. Именно поэтому инженерный журнал с историей каждой ошибки в правиле здесь важнее списка возможностей: он показывает, на каком коде получены цифры. Каждое расширение, новый провайдер или новый язык, до сих пор вскрывало собственный класс ложных срабатываний. Поле provider в каждом правиле и конфигурация PROVIDERS выглядят как заготовка под другие API помимо этих двух.
После двух структурных условий в litellm осталось 2 находки вместо 1 720
Первая версия сканера сопоставляла регулярные выражения с текстом файла целиком. На шести публичных репозиториях (anthropic-cookbook, anthropic-sdk-python, llm, aider, OpenHands, litellm) она дала 1 576 находок, и подавляющее большинство пришлось на комментарии, строки документации и вызовы других провайдеров в многопровайдерных базах, совпавшие по имени метода.
Вторая версия обходит дерево и проверяет правило на отдельных узлах, но на первом прогоне универсального движка litellm выдал 1 720 находок: 1 604 от правила о переходе с httpx на httpx2 и 114 от правила про асинхронный .with_raw_response. httpx это универсальная HTTP-библиотека, а .with_raw_response общее соглашение всех SDK, сгенерированных Stainless, включая OpenAI.
Помогли не более точные регулярные выражения, а два структурных условия: файл должен действительно импортировать anthropic, вызов должен стоять внутри async def. После этого litellm дал 2 находки, aider 0 вместо 11, а 36 оставшихся находок в anthropic-cookbook подтвердились при ручной проверке. Отдельно нашёлся двойной учёт: 427 находок из 1 478 в anthropic-sdk-python оказались дубликатами по тройке файл, строка, правило.
Правила для OpenAI сократили число находок в litellm с 195 до 59
rules_openai.py содержит 4 правила, собранных вручную из действующего руководства по миграции на httpx2, из явных пометок BREAKING CHANGES в CHANGELOG.md и из руководства по переходу на openai-python 1.0.0. ast_scan.py объединяет оба набора: правило без поля provider считается anthropic, поэтому 18 прежних правил править не пришлось.
Полный разбор находок в litellm вскрыл три ошибки. Условие «файл импортирует openai» срабатывало там, где openai.types используется как общий словарь типов для чужих провайдеров, вплоть до обработчика генерации изображений Vertex AI: 170 ложных срабатываний правила про httpx на первом прогоне.
Из 129 срабатываний этого правила 63 пришлись на голую строку импорта httpx, без единого создания клиента или таймаута в файле; в 43 файлах это было единственное совпадение. Ещё одно срабатывание оказалось строковым литералом с именем openai.ChatCompletion.create внутри логирующего вызова интеграции PromptLayer. После трёх правок в litellm осталось 59 находок, все проверены поштучно, а на 224 файлах openai-cookbook сканер не нашёл ничего.
Еженедельное задание открыло первый PR с новыми правилами за 59 секунд
autofix.py правит код для 5 правил из примерно 19, где изменение сводится к удалению аргумента или замене строки один в один. Перед записью патча файл прогоняется через ast.parse: на копии anthropic-cookbook это дало 20 правок в 9 файлах, все они после правки парсились.
sync_rules.py забирает release notes Anthropic в виде markdown, разбирает их на датированные разделы (135 штук вплоть до мая 2024 года) и отдаёт модели только те, что новее сохранённой даты. Для openai-python парсер сначала фильтрует CHANGELOG.md по заголовкам BREAKING CHANGES: из 344 версий такую пометку получили две.
Один из запусков на GitHub Actions упал на JSONDecodeError: модель писала в поле pattern одиночные обратные слэши, невалидные для JSON. Следующий остановила настройка репозитория, запрещавшая Actions открывать pull request. Ещё один прошёл целиком за 59 секунд и открыл PR #1 с новыми правилами.
Слепая зона сырых HTTP-вызовов
Интеграции, которые собирают JSON вручную и шлют его на api.anthropic.com в обход SDK, сканер не видит вовсе: правила описывают форму вызова SDK. Собственная интеграция litellm с Anthropic и старый Node-прототип с зашитым claude-sonnet-4-20250514 дают ноль находок именно поэтому.
Вызовы, собранные через **kwargs и слои абстракции, тоже проходят мимо. JS/TS-сканер знает пока только правила Anthropic и проверен на двух репозиториях: в vercel/ai после четырёх исправлений осталось 67 находок из 1 734. Синхронизация правил OpenAI на реальном ломающем изменении ещё не проверялась.
Комментарии
Пока никто не написал. Будьте первым.
Присоединяйтесь к разговору
Войдите через Google, чтобы оставить комментарий. Имя и аватар подставятся из вашего профиля Google, а комментарий появится после модерации.
Из Google мы используем только имя и аватар. Почту не сохраняем.
