zeroclaw/tests
Aleksandr Prilipko 3a4e55b68d feat(providers): auto-refresh expired Gemini OAuth tokens in warmup
Добавлен автоматический refresh протухших OAuth токенов Gemini при вызове warmup().

## Проблема

При использовании Gemini как fallback провайдера, OAuth токены могут протухнуть пока daemon работает. Это приводит к ошибкам при попытке переключения с OpenAI Codex на Gemini.

Сценарий:
1. Daemon работает, но не делает запросов к Gemini
2. OAuth токены Gemini истекают (TTL = 1 час)
3. Происходит ошибка на OpenAI Codex → fallback на Gemini
4. Gemini провайдер использует протухшие токены → запрос падает

## Решение

### Изменения в `GeminiProvider::warmup()`

Добавлена проверка и обновление токенов для `ManagedOAuth`:
- Вызывается `AuthService::get_valid_gemini_access_token()` который автоматически обновляет токены если нужно
- Для `OAuthToken` (CLI): пропускается (существующее поведение)
- Для API key: проверяется через публичный API (существующее поведение)

### Тесты

**Unit тесты** (`src/providers/gemini.rs`):
- `warmup_managed_oauth_requires_auth_service()` — проверка что ManagedOAuth требует auth_service
- `warmup_cli_oauth_skips_validation()` — проверка что CLI OAuth пропускает валидацию

**E2E тест** (`tests/gemini_fallback_oauth_refresh.rs`):
- `gemini_warmup_refreshes_expired_oauth_token()` — live тест с expired токеном и реальным refresh
- `gemini_warmup_with_valid_credentials()` — простой тест что warmup работает с валидными credentials

### Зависимости

Добавлена dev-зависимость `scopeguard = "1.2"` для безопасного восстановления файлов в тестах.

## Верификация

Проверено на live daemon с Telegram ботом:
- OpenAI Codex упал с 429 rate limit
- Fallback на Gemini сработал успешно
- Бот ответил через Gemini без ошибок

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 14:55:24 +08:00
..
fixtures fix(tools): file_read binary file support — PDF extraction + lossy fallback 2026-02-21 13:03:13 +08:00
agent_e2e.rs fix(provider): preserve reasoning_content in tool-call conversation history 2026-02-22 17:40:48 +08:00
agent_loop_robustness.rs fix(provider): preserve reasoning_content in tool-call conversation history 2026-02-22 17:40:48 +08:00
channel_routing.rs fix(channels): interrupt in-flight telegram requests on newer sender messages 2026-02-20 01:54:07 +08:00
config_persistence.rs fix(channels): interrupt in-flight telegram requests on newer sender messages 2026-02-20 01:54:07 +08:00
config_schema.rs feat(channel): split lark and feishu providers 2026-02-22 14:10:34 +08:00
dockerignore_test.rs chore: Remove blocking read strings 2026-02-19 14:52:29 +08:00
gemini_fallback_oauth_refresh.rs feat(providers): auto-refresh expired Gemini OAuth tokens in warmup 2026-02-23 14:55:24 +08:00
hooks_integration.rs chore(hooks): fix formatting and clippy warnings 2026-02-21 13:34:09 +08:00
memory_comparison.rs feat(memory): add session_id isolation to Memory trait (#530) 2026-02-17 07:44:05 -05:00
memory_restart.rs fix(channels): interrupt in-flight telegram requests on newer sender messages 2026-02-20 01:54:07 +08:00
otel_dependency_feature_regression.rs fix(observability): prevent otel reactor panic in non-tokio contexts 2026-02-20 16:07:50 +08:00
provider_resolution.rs chore(fmt): align formatting after main rebase 2026-02-21 14:54:19 +08:00
provider_schema.rs fix(provider): preserve reasoning_content in tool-call conversation history 2026-02-22 17:40:48 +08:00
reply_target_field_regression.rs fix(channels): enforce reply_target naming consistency 2026-02-18 19:56:31 +08:00
telegram_attachment_fallback.rs fix(telegram): fall back to text link when media-by-URL fails 2026-02-21 12:34:33 +08:00
whatsapp_webhook_security.rs fix(memory): prevent autosave key collisions across runtime flows 2026-02-15 22:55:52 -05:00