GitHub
В этом руководстве описана настройка канала Qwen Code, который отслеживает уведомления GitHub и отвечает на упоминания, запросы ревью, назначения и активность в отслеживаемых тредах.
Предварительные требования
- Учётная запись GitHub с правами, необходимыми для чтения уведомлений и публикации комментариев
- Установленный GitHub CLI на хосте, где запущен Qwen Code, если используется локальная аутентификация
gh
Используйте отдельную учётную запись бота, если аутентифицированная учётная запись также должна управлять каналом. GitHub не генерирует уведомление для активности собственной учётной записи, а адаптер игнорирует собственные комментарии, чтобы предотвратить циклы ответов.
Аутентификация
Чтобы переиспользовать логин GitHub CLI на хосте Qwen Code, выполните аутентификацию gh и явно установите useLocalGh: true в конфигурации канала:
gh auth loginЛокальная аутентификация gh действует на всю учётную запись и может раскрыть уведомления из каждого репозитория, доступного этой учётной записи GitHub. Включайте её, только если оператор рабочего пространства доверен для использования этой учётной записи. В противном случае настройте выделенный PAT.
Для GitHub Enterprise Server выполните аутентификацию на том же хосте, что используется в baseUrl:
gh auth login --hostname github.example.comВместо этого можно настроить классический personal access token (PAT). Явный token переопределяет локальную аутентификацию gh. PAT требует следующие scope:
- notifications — чтение тредов уведомлений
- public_repo (или repo для приватных репозиториев) — публикация комментариев
Конфигурация
Добавьте канал в ~/.qwen/settings.json:
{
"channels": {
"my-github": {
"type": "github",
"useLocalGh": true,
"pollInterval": 60000,
"reasonFilter": ["mention", "review_requested", "assign"],
"senderPolicy": "allowlist",
"allowedUsers": ["operator-github-username"],
"sessionScope": "chat_thread",
"cwd": "/path/to/your/project",
"blockStreaming": "off",
"groupPolicy": "open",
"groups": {
"*": { "requireMention": true }
}
}
}
}Чтобы переопределить локальную аутентификацию gh с помощью PAT, добавьте "token": "$GITHUB_TOKEN" в канал и установите переменную окружения перед запуском Qwen Code:
export GITHUB_TOKEN="ghp_your_token_here"Аутентифицированная учётная запись не может запускать собственный канал. Если этой учётной записи нужно управлять каналом, аутентифицируйте отдельную учётную запись бота и поместите в allowedUsers только учётные записи операторов. При запуске отклоняется allowlist, содержащий только аутентифицированную учётную запись, и выводится предупреждение, если она указана вместе с другими операторами.
GitHub Enterprise
Для GitHub Enterprise Server установите baseUrl:
{
"baseUrl": "https://github.example.com/api/v3"
}Локальная аутентификация gh требует HTTPS для baseUrl, чтобы учётные данные хоста демона не передавались по открытому HTTP.
Параметры конфигурации
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
token | не задан | Опциональный классический PAT со scope notifications; переопределяет локальную аутентификацию gh |
useLocalGh | false | Явно переиспользовать аутентификацию GitHub CLI на хосте демона для всей учётной записи |
pollInterval | 60000 | Интервал опроса в мс |
baseUrl | https://api.github.com | Базовый URL API (для GHE) |
groupPolicy | "disabled" | Должен быть "open", чтобы уведомления поступали |
senderPolicy | "allowlist" | Кто может запускать бота |
groups.*.requireMention | true | Требовать @упоминания для обычных комментариев; направленные причины уведомлений всё равно выполняются |
blockStreaming | "off" | Всегда принудительно "off"; промежуточные чанки модели не публикуются; "on" не поддерживается |
reasonFilter | не задан | Опциональный allowlist причин уведомлений GitHub для обработки |
Используйте reasonFilter, чтобы отфильтровать шумные классы уведомлений, такие как ci_activity или state_change. Не используйте reasonFilter: ["mention"] как замену groups.*.requireMention: причина mention в GitHub закрепляется на уровне треда, поэтому реальные новые @упоминания могут приходить позже с причинами comment, subscribed, author или другими и будут пропущены.
Допустимые значения reasonFilter: mention, review_requested, assign, author, comment, ci_activity, manual, state_change, subscribed, team_mention, security_alert, approval_requested, invitation, member_feature_requested и security_advisory_credit.
Отфильтрованные уведомления помечаются как прочитанные только после завершения всей принятой работы в окне опроса. Удаление фильтра позже не воспроизведёт уведомления, которые канал уже пропустил.
⚠️ Безопасность
В публичном репозитории установка senderPolicy: "open" позволяет любому пользователю GitHub, вызвавшему поддерживаемую причину уведомления, отправлять промпты, которые управляют агентом в вашем cwd. Это включает чтение кода, расходование токенов, публикацию комментариев и (в соответствии с политикой разрешений) запуск инструментов.
Всегда используйте senderPolicy: "allowlist" с явным allowedUsers в публичных репозиториях.
Записи allowlist и pairing привязаны к имени пользователя, а не к неизменному ID учётной записи. Если пользователь из allowlist переименовывает свою учётную запись GitHub, удалите устаревшую запись — GitHub освобождает старое имя пользователя, и любой другой может его занять, и новый владелец унаследует авторизацию allowlist/pairing.
Обнаружение упоминаний
Адаптер обнаруживает упоминания, сканируя текст комментариев и первые обращения issue или PR на наличие @bot-username с помощью регистронезависимого regex. Он не доверяет только reason: "mention", потому что это значение закрепляется на уровне треда. Другие причины выбирают промпты ревью, триажа, отслеживаемого треда или фолбэк.
Как это работает
Адаптер использует Notifications API GitHub как сигнал пробуждения:
- Опрос
GET /notificationsдля непрочитанных тредов - Перечисление комментариев через
listCommentsв скользящем временном окне на основе курсора - Сохранение принятой работы перед диспетчеризацией, включая конверт источника и ключи дедупликации
- Диспетчеризация по причине уведомления: строгое соответствие упоминания, ревью pull request, триаж issue, агрегация комментариев отслеживаемого треда или фолбэк для каждого комментария
- Фиксация окна опроса только после завершения принятой работы: пометка уведомлений как прочитанных и перемещение курсора
- Фолбэк первого контакта: тело нового непрочитанного issue/PR может быть обработано, если ни один комментарий не был отправлен; уведомления об упоминаниях всё равно требуют фактического упоминания в теле
Окно комментариев — это (previousCursor, currentMaxUpdatedAt]. Принятые, выполняющиеся и завершённые с ошибкой задачи хранятся в ~/.qwen/channels/<workspace-scope>/ с приватными правами доступа к файлам. При перезапуске канал восстанавливает эти задачи перед повторным опросом GitHub. Задачи с ошибкой повторяются до трёх раз, затем становятся терминальными; отменённые задачи являются терминальными и не перезапускаются. Задача, финальный ответ которой уже был опубликован, подавлен или поставлен в очередь для определённой повторной попытки без записи, не перезапускается.
Курсор уведомлений не продвигается, пока остаются восстанавливаемые задачи или когда состояние входящих задач не может быть прочитано или записано. Это предотвращает потерю принятого комментария при сбое или ошибке агента и сохраняет ключи дедупликации, необходимые для предотвращения повторной диспетчеризации из ленты уведомлений.
Активность без комментариев (push, изменения label) обновляет updated_at уведомления, но не создаёт новых комментариев в окне, поэтому повторно полученные треды пропускаются без запуска агента.
Обратная связь по ответу
Для принятого комментария к issue или pull request канал добавляет реакцию GitHub 👀, пока агент работает, затем удаляет её при завершении, ошибке или отмене. Обе операции выполняются по принципу best-effort: ошибка API реакций или прав доступа логируется и никогда не препятствует финальному ответу.
Только финальный вывод
Канал GitHub всегда принудительно использует только финальную доставку. Адаптер устанавливает blockStreaming в "off", поэтому промежуточные чанки модели никогда не публикуются как отдельные комментарии, и blockStreaming: "on" не поддерживается.
{
"blockStreaming": "off"
}Если GitHub возвращает определённый отказ доставки без записи, например ответ rate-limit, канал сохраняет финальный ответ в
~/.qwen/channels/<workspace-scope>/<channel>-<name-hash>-github-pending-deliveries.json
с приватными правами доступа к файлам и повторяет попытку при следующем запуске канала. Соответствующая входящая задача остаётся в состоянии reply_pending, пока эта доставка не завершится успешно или не достигнет определённого терминального сбоя. Неоднозначные сбои доставки не повторяются автоматически, потому что GitHub мог создать комментарий.
Известные ограничения
- Первый запуск пропускает существующие непрочитанные уведомления. Курсор инициализируется значением «сейчас» при первом запуске. Уведомления, созданные до запуска бота, не обрабатываются, если только тред не получит новую активность после этого.
- Если пользователь помечает уведомление как прочитанное на github.com до цикла опроса бота, бот его не обработает.
- Бот не читает комментарии до текущего окна опроса; уведомления
authorиcommentмогут агрегировать до 20 комментариев из этого окна. - Inline-комментарии ревью PR и тела сводок ревью не перечисляются; обрабатываются только комментарии issue/PR.
- Выбранные учётные данные должны поддерживать Notifications API. Fine-grained PAT не поддерживают его; используйте локальную аутентификацию
ghили классический PAT со scopenotifications.
Запуск канала
qwen channel start my-github